Tracks
/
Crystal
Crystal
/
Ejercicios
/
Fusionista de fotos
Fusionista de fotos

Fusionista de fotos

Ejercicio de aprendizaje

Introducción

El binario, el octal y el hexadecimal (también conocido como hex) son distintos sistemas de numeración con bases diferentes. El binario es base 2, el octal es base 8 y el hexadecimal es base 16. Los enteros normales son base 10 en Crystal. El binario, el octal y el hexadecimal son representaciones de números enteros. Esto significa que representan números positivos y negativos (incluido el cero) sin fracciones ni decimales, y admiten todas las operaciones que podemos hacer con números enteros.

Binario

El binario es un sistema de numeración de base 2 que usa solo los dígitos 0 y 1. Suele representar los estados 0 («apagado») y 1 («encendido») del flujo eléctrico a través de transistores e interruptores en las computadoras, así como las cargas positiva y negativa en los medios de almacenamiento magnético. El binario puede representar todos los números enteros que se usan en base 10.

Un fragmento del sistema de base 2 se ve así, aunque continúa infinitamente y no se detiene en 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

Entonces, si queremos representar el número 6, en binario sería: 110

Valor posicional 4 2 1
Número binario 1 1 0

Y la operación sería: 4 + 2 + 0 = 6

Otro ejemplo: 19

Valor posicional 16 8 4 2 1
Número binario 1 0 0 1 1

El número binario sería: 10011 Y la operación sería: 16 + 0 + 0 + 2 + 1 = 19

Binario en Crystal

En Crystal, podemos representar literales binarios usando el prefijo 0b. Si escribimos 0b10011, Crystal lo interpretará como un número binario y lo convertirá a base 10.

0b10011
# => 19

typeof(0b10011)
# => Int32

Si escribes un número con el prefijo 0b que no esté en el sistema binario, se generará un error de compilación.

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

Operaciones con números binarios

Como los números binarios son enteros, podemos realizar con ellos todas las operaciones que podemos hacer con enteros.

0b10011 + 0b10011
# => 38

0b10011 * 0b10011
# => 361

0b10011 / 3
# => 6.333333333333333

Convertir a y desde la representación binaria

Crystal convertirá automáticamente un literal binario a Int32. Para convertir un Int32 a una representación binaria, usa el método <int>.to_s(base) con el argumento base establecido en 2. El método devolverá una representación en string del número binario:

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

Para convertir una representación en string de un binario a un entero, podemos usar el método <int>.to_i(base), pasando la base (2) como argumento:

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

Dar la base incorrecta (o una representación binaria no válida) generará un ArgumentError:

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

Métodos binarios

Hay ciertos métodos que se pueden usar en los enteros para obtener información sobre la representación binaria del número.

<int>.bit_length devolverá la cantidad de bits que se necesitan para representar el número:

19.bit_length
# => 5

<int>.bit(index) devolverá el bit en el índice dado, empezando por la derecha (el bit menos significativo):

19.bit(0)
# => 1

0b10011.bit(1)
# => 1

Octal

El octal es un sistema de numeración de base 8. Usa los dígitos 0, 1, 2, 3, 4, 5, 6 y 7.

En Crystal, podemos representar números octales usando el prefijo 0o. Al igual que con el binario, Crystal convierte automáticamente una representación octal a un Int32.

0o123
# => 83

Poner el prefijo 0o a un número que no esté en el sistema octal generará un error de compilación.

Convertir a y desde la representación octal

Al igual que con el binario, podemos usar el método <int>.to_s(base) para convertir un Int32 a una representación octal. Y podemos usar el método <int>.to_i(base) para convertir una representación octal a un Int32.

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

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

Al igual que con el binario, dar la base incorrecta generará un ArgumentError.

Hexadecimal

El hexadecimal es un sistema de numeración de base 16. Usa los dígitos 0 - 9 y las letras A, B, C, D, E y F. A es 10, B es 11, C es 12, D es 13, E es 14 y F es 15.

Podemos representar números hexadecimales en Crystal usando el prefijo 0x. Al igual que con el binario y el octal, Crystal convertirá automáticamente los literales hexadecimales a Int32.

#=> 0x123
291

Poner el prefijo 0x a un número que no sea hexadecimal generará un error de compilación.

Convertir a y desde la representación hexadecimal

Al igual que con el binario, podemos usar el método <int>.to_s(base) para convertir un Int32 a una representación hexadecimal. Y podemos usar el método <int>.to_i(base) para convertir una representación hexadecimal a un Int32.

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

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

Al igual que con el binario y el octal, dar la base incorrecta generará un ArgumentError.

Precisión

Al convertir un número a una representación en string, podemos especificar la precisión del número. Es decir, la cantidad mínima de números usados para representar el número. Si el número tiene menos dígitos que la precisión, se agregarán ceros a la izquierda a la representación en string. Esto se hace pasando el argumento precision al método <int>.to_s(<base>, precision: <value>).

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

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

Instrucciones

Tu amigo se cansó de pagar por un software de edición de fotos y decidió escribir el suyo. Tu amigo decidió llamar al nuevo software Foto Fusionist.

Foto Fusionist es un software de edición de fotos que puede hacer muchas cosas, pero hasta ahora solo has implementado algunas. Sin embargo, tu amigo está muy contento con el progreso y te pidió que implementes algunas funcionalidades más.

1. Convertir una representación binaria a un número entero

Para la primera funcionalidad, tu amigo quiere poder convertir la representación binaria de un número a un número entero. Esto es necesario porque el software podrá leer la representación binaria de un canal de color y convertirla a un número entero.

Implementa el método FotoFusionist.binary_to_int, que recibe un argumento binary de tipo String. El método debe devolver la representación del número binario como número entero.

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

2. Obtener el bit menos significativo de un número entero

La segunda funcionalidad que quiere tu amigo es poder obtener el bit menos significativo de un número entero. El bit menos significativo es el bit que está más a la derecha. Se llama bit menos significativo porque es el que tiene el menor valor.

El bit menos significativo es necesario para evaluar si una imagen se puede optimizar reduciendo la cantidad de bits que se usan para representar el canal de color.

Implementa el método FotoFusionist.least_significant_bit, que recibe un argumento number de tipo Int32. El método debe devolver el bit menos significativo del número.

FotoFusionist.least_significant_bit(0b10011)
# => 1

FotoFusionist.least_significant_bit(0b10010)
# => 0

3. Obtener el valor hexadecimal de un canal de color

La tercera funcionalidad que quiere tu amigo es poder obtener el valor hexadecimal de un canal de color. El valor hexadecimal es necesario para poder convertir el canal de color a una representación hexadecimal, y esa representación hexadecimal debe estar formada por dos dígitos.

Implementa el método FotoFusionist.hex_value, que recibe un argumento number de tipo Int32. El método debe devolver el valor hexadecimal del número como un String.

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

4. Obtener el valor hexadecimal de un color RGB

La cuarta funcionalidad que quiere tu amigo es poder obtener el valor hexadecimal de un color RGB. Esto es necesario para que quien use el programa pueda obtener una única representación de un color como string. Un color RGB es un color que se representa mediante tres canales de color: rojo, verde y azul. Cada canal de color se representa con un número entre 0 y 255.

El valor hexadecimal de un color RGB es una representación del color en hexadecimal como string, con el canal de color rojo primero, luego el canal de color verde y por último el canal de color azul.

Implementa el método FotoFusionist.hex_value_from_rgb, que recibe tres argumentos: red, green y blue de tipo Int32. El método debe devolver el valor hexadecimal del color RGB como un String.

FotoFusionist.hex_value_from_rgb(255, 0, 0)
# => "ff0000"
Editar en GitHub El enlace se abre en una ventana o una pestaña nuevas
Crystal Exercism

¿Todo listo para empezar Fusionista de fotos?

Regístrate en Exercism para aprender y dominar Crystal con 26 conceptos142 ejercicios y mentoría humana real, todo gratis.