293 lines
15 KiB
Markdown
293 lines
15 KiB
Markdown
|
---
|
||
|
title: Caesars Cipher
|
||
|
localeTitle: Cifrado de Caesars
|
||
|
---
|
||
|
![:triangular_flag_on_post:](https://forum.freecodecamp.com/images/emoji/emoji_one/triangular_flag_on_post.png?v=3 ": triangular_flag_on_post:") Recuerda usar **`Read-Search-Ask`** si te atascas. Tratar de emparejar el programa ![:busts_in_silhouette:](https://forum.freecodecamp.com/images/emoji/emoji_one/busts_in_silhouette.png?v=3 ": busts_in_silhouette:") y escribe tu propio código ![:pencil:](https://forum.freecodecamp.com/images/emoji/emoji_one/pencil.png?v=3 ":lápiz:")
|
||
|
|
||
|
### ![:checkered_flag:](https://forum.freecodecamp.com/images/emoji/emoji_one/checkered_flag.png?v=3 ":bandera a cuadros:") Explicación del problema:
|
||
|
|
||
|
* Necesita escribir una función, que tomará una cadena codificada con _cifrado César_ como parámetro y la decodificará.
|
||
|
* El que se usa aquí es ROT13, donde el valor de la letra se desplaza 13 lugares. por ejemplo, 'A' ![:left_right_arrow:](https://forum.freecodecamp.com/images/emoji/emoji_one/left_right_arrow.png?v=3 ": left_right_arrow:") 'N', 'T' ![:left_right_arrow:](https://forum.freecodecamp.com/images/emoji/emoji_one/left_right_arrow.png?v=3 ": left_right_arrow:") 'SOL'.
|
||
|
* Tienes que cambiarlo 13 posiciones hacia atrás, de modo que 'N' ![:left_right_arrow:](https://forum.freecodecamp.com/images/emoji/emoji_one/left_right_arrow.png?v=3 ": left_right_arrow:") 'UNA'.
|
||
|
|
||
|
#### Enlaces relevantes
|
||
|
|
||
|
* [String.prototype.charCodeAt](http://forum.freecodecamp.com/t/javascript-string-prototype-charcodeat/15933)
|
||
|
* String.fromCharCode
|
||
|
|
||
|
## ![:speech_balloon:](https://forum.freecodecamp.com/images/emoji/emoji_one/speech_balloon.png?v=3 ": speech_balloon:") Sugerencia: 1
|
||
|
|
||
|
Use _String.charCodeAt ()_ para convertir el carácter inglés a ASCII.
|
||
|
|
||
|
> _intenta resolver el problema ahora_
|
||
|
|
||
|
## ![:speech_balloon:](https://forum.freecodecamp.com/images/emoji/emoji_one/speech_balloon.png?v=3 ": speech_balloon:") Sugerencia: 2
|
||
|
|
||
|
Use _String.fromCharCode ()_ para convertir ASCII a caracteres en inglés.
|
||
|
|
||
|
> _intenta resolver el problema ahora_
|
||
|
|
||
|
## ![:speech_balloon:](https://forum.freecodecamp.com/images/emoji/emoji_one/speech_balloon.png?v=3 ": speech_balloon:") Sugerencia: 3
|
||
|
|
||
|
Deja cualquier cosa que no se interponga entre AZ como es.
|
||
|
|
||
|
> _intenta resolver el problema ahora_
|
||
|
|
||
|
## ¡Alerta de spoiler!
|
||
|
|
||
|
![señal de advertencia](//discourse-user-assets.s3.amazonaws.com/original/2X/2/2d6c412a50797771301e7ceabd554cef4edcd74d.gif)
|
||
|
|
||
|
**¡Solución por delante!**
|
||
|
|
||
|
## ![:beginner:](https://forum.freecodecamp.com/images/emoji/emoji_one/beginner.png?v=3 ":principiante:") Solución de código básico:
|
||
|
|
||
|
```javascript
|
||
|
function rot13(str) {
|
||
|
// Split str into a character array
|
||
|
return str.split('')
|
||
|
// Iterate over each character in the array
|
||
|
.map.call(str, function(char) {
|
||
|
// Convert char to a character code
|
||
|
x = char.charCodeAt(0);
|
||
|
// Checks if character lies between AZ
|
||
|
if (x < 65 || x > 90) {
|
||
|
return String.fromCharCode(x); // Return un-converted character
|
||
|
}
|
||
|
//N = ASCII 78, if the character code is less than 78, shift forward 13 places
|
||
|
else if (x < 78) {
|
||
|
return String.fromCharCode(x + 13);
|
||
|
}
|
||
|
// Otherwise shift the character 13 places backward
|
||
|
return String.fromCharCode(x - 13);
|
||
|
}).join(''); // Rejoin the array into a string
|
||
|
}
|
||
|
```
|
||
|
|
||
|
![:rocket:](https://forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=3 ":cohete:") [Ejecutar código](https://repl.it/CLjU/38)
|
||
|
|
||
|
### Explicación del código:
|
||
|
|
||
|
* Una variable de cadena `nstr` se declara y se inicializa para almacenar la cadena descodificada.
|
||
|
* El bucle for se utiliza para recorrer cada carácter de la cadena de entrada.
|
||
|
* Si el carácter no es alfabetos en mayúsculas (es decir, su ascii no está entre 65 y 91), lo dejaremos como está y [continuaremos](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue) con la siguiente iteración.
|
||
|
* Si es el alfabeto en mayúsculas, restaremos 13 de su código ASCII.
|
||
|
* Si el código ASCII es menor que 78, se saldrá del rango cuando se reste a 13, así que le agregaremos 26 (número de letras en alfabetos en inglés) para que después de A regrese a Z. por ejemplo, M (77) ![:left_right_arrow:](https://forum.freecodecamp.com/images/emoji/emoji_one/left_right_arrow.png?v=3 ": left_right_arrow:") 77-13 = 64 (no es un alfabeto inglés) +26 = 90 ![:left_right_arrow:](https://forum.freecodecamp.com/images/emoji/emoji_one/left_right_arrow.png?v=3 ": left_right_arrow:") Z (90).
|
||
|
|
||
|
#### Enlaces relevantes
|
||
|
|
||
|
* [Array.prototype.map](http://forum.freecodecamp.com/t/javascript-array-prototype-map/14294)
|
||
|
* [String.prototype.split](http://forum.freecodecamp.com/t/javascript-string-prototype-split/15944)
|
||
|
* [Array.prototype.join](http://forum.freecodecamp.com/t/javascript-array-prototype-join/14292)
|
||
|
|
||
|
## ![:sunflower:](https://forum.freecodecamp.com/images/emoji/emoji_one/sunflower.png?v=3 ":girasol:") Solución de código intermedio:
|
||
|
|
||
|
```javascript
|
||
|
// Solution with Regular expression and Array of ASCII character codes
|
||
|
function rot13(str) {
|
||
|
var rotCharArray = [];
|
||
|
var regEx = /[AZ]/ ;
|
||
|
str = str.split("");
|
||
|
for (var x in str) {
|
||
|
if (regEx.test(str[x])) {
|
||
|
// A more general approach
|
||
|
// possible because of modular arithmetic
|
||
|
// and cyclic nature of rot13 transform
|
||
|
rotCharArray.push((str[x].charCodeAt() - 65 + 13) % 26 + 65);
|
||
|
} else {
|
||
|
rotCharArray.push(str[x].charCodeAt());
|
||
|
}
|
||
|
}
|
||
|
str = String.fromCharCode.apply(String, rotCharArray);
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
// Change the inputs below to test
|
||
|
rot13("LBH QVQ VG!");
|
||
|
```
|
||
|
|
||
|
### Explicación del código:
|
||
|
|
||
|
* Se crea una matriz vacía en una variable llamada `rotCharArray` para almacenar los códigos de caracteres.
|
||
|
* La variable `regEx` almacena una expresión regular para todas las letras mayúsculas de la A a la Z.
|
||
|
* Dividimos `str` en una matriz de caracteres y luego usamos un bucle for para recorrer cada carácter de la matriz.
|
||
|
* Usando una instrucción if, probamos si la cadena solo contiene letras mayúsculas de la A a la Z.
|
||
|
* Si devuelve true, usamos la función `charCodeAt()` y la transformación rot13 para devolver el valor correcto, de lo contrario, devolveremos el valor inicial.
|
||
|
* Luego devolvemos la cadena con los códigos de caracteres de la variable `rotCharArray` .
|
||
|
|
||
|
### Explicación del algoritmo:
|
||
|
```
|
||
|
ALPHA KEY BASE ROTATED ROT13
|
||
|
-------------------------------------------------------------
|
||
|
[A] 65 <=> 0 + 13 => 13 % 26 <=> 13 + 65 = 78 [N]
|
||
|
[B] 66 <=> 1 + 13 => 14 % 26 <=> 14 + 65 = 79 [O]
|
||
|
[C] 67 <=> 2 + 13 => 15 % 26 <=> 15 + 65 = 80 [P]
|
||
|
[D] 68 <=> 3 + 13 => 16 % 26 <=> 16 + 65 = 81 [Q]
|
||
|
[E] 69 <=> 4 + 13 => 17 % 26 <=> 17 + 65 = 82 [R]
|
||
|
[F] 70 <=> 5 + 13 => 18 % 26 <=> 18 + 65 = 83 [S]
|
||
|
[G] 71 <=> 6 + 13 => 19 % 26 <=> 19 + 65 = 84 [T]
|
||
|
[H] 72 <=> 7 + 13 => 20 % 26 <=> 20 + 65 = 85 [U]
|
||
|
[I] 73 <=> 8 + 13 => 21 % 26 <=> 21 + 65 = 86 [V]
|
||
|
[J] 74 <=> 9 + 13 => 22 % 26 <=> 22 + 65 = 87 [W]
|
||
|
[K] 75 <=> 10 + 13 => 23 % 26 <=> 23 + 65 = 88 [X]
|
||
|
[L] 76 <=> 11 + 13 => 24 % 26 <=> 24 + 65 = 89 [Y]
|
||
|
[M] 77 <=> 12 + 13 => 25 % 26 <=> 25 + 65 = 90 [Z]
|
||
|
[N] 78 <=> 13 + 13 => 26 % 26 <=> 0 + 65 = 65 [A]
|
||
|
[O] 79 <=> 14 + 13 => 27 % 26 <=> 1 + 65 = 66 [B]
|
||
|
[P] 80 <=> 15 + 13 => 28 % 26 <=> 2 + 65 = 67 [C]
|
||
|
[Q] 81 <=> 16 + 13 => 29 % 26 <=> 3 + 65 = 68 [D]
|
||
|
[R] 82 <=> 17 + 13 => 30 % 26 <=> 4 + 65 = 69 [E]
|
||
|
[S] 83 <=> 18 + 13 => 31 % 26 <=> 5 + 65 = 70 [F]
|
||
|
[T] 84 <=> 19 + 13 => 32 % 26 <=> 6 + 65 = 71 [G]
|
||
|
[U] 85 <=> 20 + 13 => 33 % 26 <=> 7 + 65 = 72 [H]
|
||
|
[V] 86 <=> 21 + 13 => 34 % 26 <=> 8 + 65 = 73 [I]
|
||
|
[W] 87 <=> 22 + 13 => 35 % 26 <=> 9 + 65 = 74 [J]
|
||
|
[X] 88 <=> 23 + 13 => 36 % 26 <=> 10 + 65 = 75 [K]
|
||
|
[Y] 89 <=> 24 + 13 => 37 % 26 <=> 11 + 65 = 76 [L]
|
||
|
[Z] 90 <=> 25 + 13 => 38 % 26 <=> 12 + 65 = 77 [M]
|
||
|
```
|
||
|
|
||
|
#### Enlaces relevantes
|
||
|
|
||
|
* [Función.aplicar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
|
||
|
* [Regex](https://forum.freecodecamp.com/t/regular-expressions-resources/15931)
|
||
|
* [Regex.test](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test)
|
||
|
|
||
|
![:rocket:](https://forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=3 ":cohete:") [Ejecutar código](https://repl.it/CLjU/39)
|
||
|
|
||
|
## ![:rotating_light:](https://forum.freecodecamp.com/images/emoji/emoji_one/rotating_light.png?v=3 ": rotando luz:") Solución avanzada de código:
|
||
|
```
|
||
|
function rot13(str) { // LBH QVQ VG!
|
||
|
return str.replace(/[AZ]/g, L => String.fromCharCode((L.charCodeAt(0) % 26) + 65));
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### Explicación del algoritmo:
|
||
|
|
||
|
Comprender el operador de módulo (a _veces llamado operador de módulo_ ) representado simbólicamente como `%` en JavaScript es clave para entender el algoritmo.
|
||
|
Este es un operador interesante que aparece en varios lugares de Ingeniería, por ejemplo, en criptografía.
|
||
|
|
||
|
Básicamente, operado en un número, divide el número por el divisor dado y da el resto de la división.
|
||
|
Por ejemplo,
|
||
|
|
||
|
* `0 % 5 = 0` porque `0 / 5 = 0` y el resto es `0` .
|
||
|
|
||
|
* `2 % 5 = 2` porque `2 / 5 = 0` y el resto es `2`
|
||
|
|
||
|
* `4 % 5 = 4` porque `4 / 5 = 0` y el resto es `4`
|
||
|
|
||
|
* `5 % 5 = 0` porque `5 / 5 = 1` y el resto es `0`
|
||
|
|
||
|
* `7 % 5 = 2` porque `7 / 5 = 1` y el resto es `2`
|
||
|
|
||
|
* `9 % 5 = 4` porque `9 / 5 = 1` y el resto es `4`
|
||
|
|
||
|
* `10 % 5 = 0` porque `10 / 5 = 2` y el resto es `0`
|
||
|
|
||
|
|
||
|
Pero debes haber notado un patrón aquí.
|
||
|
Como habrás notado, el increíble operador de módulo envuelve el valor de LHS cuando solo alcanza los múltiplos del valor de RHS.
|
||
|
por ejemplo, en nuestro caso, cuando `LHS = 5` , se ajustó a `0`
|
||
|
O
|
||
|
cuando `LHS = 10` , volvió a `0` .
|
||
|
|
||
|
Por lo tanto, vemos el siguiente patrón emergente
|
||
|
```
|
||
|
0 ⇔ 0
|
||
|
1 ⇔ 1
|
||
|
2 ⇔ 2
|
||
|
3 ⇔ 3
|
||
|
4 ⇔ 4
|
||
|
5 ⇔ 0
|
||
|
6 ⇔ 1
|
||
|
7 ⇔ 2
|
||
|
8 ⇔ 3
|
||
|
9 ⇔ 4
|
||
|
10 ⇔ 0
|
||
|
```
|
||
|
|
||
|
Por lo tanto, llegamos a la conclusión de que al utilizar el operador de módulo, se puede asignar un rango de valores a un rango entre \[ `0` a `DIVISOR - 1` \]. En nuestro caso, mapeamos \[ `5 - 9` \] entre \[ `0 - 4` \] o mapeamos \[ `6 - 10` \] entre \[ `0 - 4` \].
|
||
|
|
||
|
¿Entendiste hasta esto?
|
||
|
|
||
|
Ahora consideremos la posibilidad de asignar un rango de `26` números, es decir, entre \[ `65 - 90` \] que representa \[ **Alfabetos ingleses** \] en mayúsculas en un [juego de caracteres Unicode](http://unicode-table.com/en/alphabets/) a un rango de números entre \[ `0 - 25` \].
|
||
|
```
|
||
|
[A] 65 % 26 ⇔ 13
|
||
|
[B] 66 % 26 ⇔ 14
|
||
|
[C] 67 % 26 ⇔ 15
|
||
|
[D] 68 % 26 ⇔ 16
|
||
|
[E] 69 % 26 ⇔ 17
|
||
|
[F] 70 % 26 ⇔ 18
|
||
|
[G] 71 % 26 ⇔ 19
|
||
|
[H] 72 % 26 ⇔ 20
|
||
|
[I] 73 % 26 ⇔ 21
|
||
|
[J] 74 % 26 ⇔ 22
|
||
|
[K] 75 % 26 ⇔ 23
|
||
|
[L] 76 % 26 ⇔ 24
|
||
|
[M] 77 % 26 ⇔ 25
|
||
|
[N] 78 % 26 ⇔ 0
|
||
|
[O] 79 % 26 ⇔ 1
|
||
|
[P] 80 % 26 ⇔ 2
|
||
|
[Q] 81 % 26 ⇔ 3
|
||
|
[R] 82 % 26 ⇔ 4
|
||
|
[S] 83 % 26 ⇔ 5
|
||
|
[T] 84 % 26 ⇔ 6
|
||
|
[U] 85 % 26 ⇔ 7
|
||
|
[V] 86 % 26 ⇔ 8
|
||
|
[W] 87 % 26 ⇔ 9
|
||
|
[X] 88 % 26 ⇔ 10
|
||
|
[Y] 89 % 26 ⇔ 11
|
||
|
[Z] 90 % 26 ⇔ 12
|
||
|
```
|
||
|
|
||
|
Como puede observar, cada número en el rango de \[ `65 - 90` \] se asigna a un número único entre \[ `0 - 25` \].
|
||
|
Es posible que también haya notado que cada número dado (por ejemplo, `65` ) se asigna a otro número (por ejemplo, `13` ) que puede usarse como un valor de compensación (es decir, `65 + OFFSET` ) para obtener el ROT13 del número dado.
|
||
|
|
||
|
Por ejemplo, `65` mapas a `13` que pueden tomarse como un valor de compensación y sumarse a `65` para dar `78` .
|
||
|
```
|
||
|
[A] 65 % 26 ⇔ 13 + 65 = 78 [N]
|
||
|
[B] 66 % 26 ⇔ 14 + 65 = 79 [O]
|
||
|
[C] 67 % 26 ⇔ 15 + 65 = 80 [P]
|
||
|
[D] 68 % 26 ⇔ 16 + 65 = 81 [Q]
|
||
|
[E] 69 % 26 ⇔ 17 + 65 = 82 [R]
|
||
|
[F] 70 % 26 ⇔ 18 + 65 = 83 [S]
|
||
|
[G] 71 % 26 ⇔ 19 + 65 = 84 [T]
|
||
|
[H] 72 % 26 ⇔ 20 + 65 = 85 [U]
|
||
|
[I] 73 % 26 ⇔ 21 + 65 = 86 [V]
|
||
|
[J] 74 % 26 ⇔ 22 + 65 = 87 [W]
|
||
|
[K] 75 % 26 ⇔ 23 + 65 = 88 [X]
|
||
|
[L] 76 % 26 ⇔ 24 + 65 = 89 [Y]
|
||
|
[M] 77 % 26 ⇔ 25 + 65 = 90 [Z]
|
||
|
[N] 78 % 26 ⇔ 0 + 65 = 65 [A]
|
||
|
[O] 79 % 26 ⇔ 1 + 65 = 66 [B]
|
||
|
[P] 80 % 26 ⇔ 2 + 65 = 67 [C]
|
||
|
[Q] 81 % 26 ⇔ 3 + 65 = 68 [D]
|
||
|
[R] 82 % 26 ⇔ 4 + 65 = 69 [E]
|
||
|
[S] 83 % 26 ⇔ 5 + 65 = 70 [F]
|
||
|
[T] 84 % 26 ⇔ 6 + 65 = 71 [G]
|
||
|
[U] 85 % 26 ⇔ 7 + 65 = 72 [H]
|
||
|
[V] 86 % 26 ⇔ 8 + 65 = 73 [I]
|
||
|
[W] 87 % 26 ⇔ 9 + 65 = 74 [J]
|
||
|
[X] 88 % 26 ⇔ 10 + 65 = 75 [K]
|
||
|
[Y] 89 % 26 ⇔ 11 + 65 = 76 [L]
|
||
|
[Z] 90 % 26 ⇔ 12 + 65 = 77 [M]
|
||
|
```
|
||
|
|
||
|
### Explicación del código:
|
||
|
|
||
|
* `String.prototype.replace` [función](http://forum.freecodecamp.com/t/javascript-string-prototype-replace/15942) `String.prototype.replace` permite transformar una `String` función de alguna coincidencia de patrón (definida por una expresión regular) y la [función de transformación](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter) (que se aplica a cada una de las coincidencias de patrón).
|
||
|
* [La](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) sintaxis de la [función de flecha](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) se usa para escribir el parámetro de la función para `replace()` .
|
||
|
* `L` representa una sola unidad, de cada coincidencia de patrón con `/[AZ]/g` - que es cada letra mayúscula en el alfabeto, de la `A` a la `Z` , presente en la cadena.
|
||
|
* La función de flecha aplica la transformación `rot13` en cada letra mayúscula del alfabeto inglés presente en la cadena dada.
|
||
|
|
||
|
#### Enlaces relevantes
|
||
|
|
||
|
* [String.prototype.replace ()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
|
||
|
|
||
|
## ![:clipboard:](https://forum.freecodecamp.com/images/emoji/emoji_one/clipboard.png?v=3 ":portapapeles:") NOTA A LOS CONTRIBUYENTES:
|
||
|
|
||
|
* ![:warning:](https://forum.freecodecamp.com/images/emoji/emoji_one/warning.png?v=3 ":advertencia:") **NO** agregue soluciones que sean similares a las soluciones existentes. Si cree que es **_similar pero mejor_** , intente fusionar (o reemplazar) la solución similar existente.
|
||
|
* Agregue una explicación de su solución.
|
||
|
* Categorice la solución en una de las siguientes categorías: **Básica** , **Intermedia** y **Avanzada** . ![:traffic_light:](https://forum.freecodecamp.com/images/emoji/emoji_one/traffic_light.png?v=3 ":semáforo:")
|
||
|
* Agregue su nombre de usuario solo si ha agregado algún **contenido principal relevante** . ( ![:warning:](https://forum.freecodecamp.com/images/emoji/emoji_one/warning.png?v=3 ":advertencia:") **_NO_** _elimine ningún nombre de usuario existente_ )
|
||
|
|
||
|
> Ver ![:point_right:](https://forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=3 ": point_right:") [**`Wiki Challenge Solution Template`**](http://forum.freecodecamp.com/t/algorithm-article-template/14272) para referencia.
|