Acceder al último elemento de un array en Javascript

Algunos lenguajes nos permiten acceder al último elemento de un array usando el índice en negativo (es decir, poniendo la posición -1) pero no es el caso de Javascript. En ese caso ¿cómo accedo al último elemento de un array? Bueno, si se trata de un lenguaje donde podamos conocer la longitud del array como es Javascript (y la mayoría de lenguajes modernos realmente) basta con usar dicha longitud como índice. En el caso concreto de Javascript tendríamos que usar la propiedad length del array pero restándole una posición (porque nunca hay que olvidar que los arrays empieza en 0):

var ultimoElemento = myArray[miArray.length - 1];

Convertir texto en inglés a 1337 con Javascript

Si ayer veíamos cómo hacer con javascript una función que codifique/descodifique un simple cifrado ROT13 hoy vamos a con otro ejercicio de javascript simple: un conversor inglés-1337.

1337, leet, leet speak o 1337 5p34k es un tipo de escritura compuesta por caracteres alfanuméricos y relativamente popular en ambientes informáticos. No se trata de ningún tipo de cifrado de mensajes, simplemente se sustituyen las letras por número o por conjuntos de símbolos cuyo aspecto recuerde al de dicho caracter.

La función sería algo así: recibe un texto escrito en el alfabeto latino internacional y lo devuelve en 1337. Creamos un objeto con todos los valores a sustituir llamado leetAlph para que nos facilite el trabajo, luego solo recorremos la cadena que recibimos como si fuese un array (en esencia toda cadena es una array de caracteres) y vamos cambiando en cada posición la letra por el valor que le corresponda.

function textoALeet(texto) { 
  let leetAlph={a:'@', 
    b:'8', 
    c:'(', 
    d:'|)',
    e: '3',
    f:'ph', 
    g:'g',
    h:'#',
    i:'l',
    j:'_|',
    k:'|<', 
    l:'1', 
    m:"|'|'|", 
    n:'/\/', 
    o:'0', 
    p:'|D', 
    q:'(,)', 
    r:'|2', 
    s:'5', 
    t:'+', 
    u:'|_|', 
    v:'|/', 
    w:"|/|/'",
    x:'><', 
    y:'j', 
    z:'2'};

  texto = texto.toLowerCase();
  for (var i = 0; i < texto.length; i++) {
    if (leetAlph[texto[i]]) {
      text = texto.replace(texto[i], leetAlph[texto[i]]);
    }
  }
  return(texto);
}

Función para cifrado ROT13 con Javascript

ROT13 es un algoritmo para el cifrado de mensajes extremadamente, tan simple que no debería ser considerado nunca una opción válida para un cifrado seguro de nuestras comunicaciones. Basado en los cifrados que se decía que realizaba Julio César en la antigüedad, donde simplemente escribía intercambiando cada letra por otra situada N posiciones más adelante o atrás en el abecedario, ROT13 consiste en desplazar cada letra de nuestro mensaje 13 posiciones hacia delante.

En su día se popularizó en los foros de internet para introducir chistes y últimamente se ha utilizado para ocultar spoilers en foros sobre series.

¿Cómo implementamos esto en Javascript? Bueno, pues se me ha ocurrido que esta sería la solución más rápida, utilizando las funciones de javascript replace() para substituir caracteres dentro de una cadena en base a una expresión regular, charCodeAt() para obtener el código del caracter y la función fromCharCode() para crear una cadena con esos códigos que obtuvimos antes y a los que les aplicamos el desplazamiento. También usaremos toLowerCase() para convertir a minúscula y evitar conflictos con los códigos de las mayúsculas.

function str_rot13(mensaje){
    return mensaje.replace(/[a-zA-Z]/gi,function(s){
        return String.fromCharCode(s.charCodeAt(0)+(s.toLowerCase()<'n'?13:-13));
    });
}

Y ahí nos quedaría un traductor inglés-rot13/rot13-inglés. Si a la función le pasamos “hola” devolverá “ubyn” y si le pasamos “ubyn” devolverá “hola. La expresión regular de la función replace() solo evalúa los caracteres del alfabeto latino internacional por lo que si le pasamos una cadena con acentos o con eñes no daría errores pero no convertiría esos caracteres, igual que hará si la cadena tiene números o símbolos. Es decir, si le pasamos la cadena “coño” devolvería “pbñb“.

Como ya comenté en la introducción se trata de un cifrado más bien “de andar por casa” o para jugar a los detectives, no algo que se pueda utilizar en el campo de la ciberseguridad y la confidencialidad de los datos.

SQL-Server: Generar un número aleatorio entre dos valores

¿Cómo genero un número aleatorio en SQL-Server? Con la función RAND(), que nos devuelve un valor float pseudoaleatorio entre 0 y 1.

¿Y cómo puedo acotar esto entre dos valores? Pues redondeando el valor de multiplicar el resultado de la función RAND() por la diferencia entre el valor más alto y más bajo que queremos usar como límites y sumándole finalmente el valor más bajo. Que así puesto solo como texto parece más lioso de lo que es, la fórmula es muy sencilla y sería:

SELECT FLOOR(RAND()*(valorHasta-valorDesde)+valorDesde);

Siendo valorHasta el valor más alto y valorDesde el más bajo entre los que queremos obtener el valor aleatorio.

Imagina que queremos un valor aleatorio entre 100 y 200:

SELECT FLOOR(RAND()*(200-100)+100);

Operaciones a bit a bit: NOT, AND, OR y XOR

Seguimos con la racha de entradas encadenadas. Si la entrada de los tipos de configuración RAID nos llevó a definir el concepto de información de paridad ahora a raíz de esa entrada vamos a hablar de las operaciones bit a bit.

Hablamos de operaciones a nivel de bit porque con ellas trabajamos directamente sobre los bits, dígitos binarios, a nivel individual. Este tipo de operaciones son muy utilizadas en computación, a la hora de cifrar datos o, como comentábamos en el otro artículo, para realizar los cálculos de paridad. Es posible que te suenen los nombres de estas operaciones, pues son operaciones lógicas que ya vimos en su día en un artículo sobre LibreOffice Calc o también en la entrada sobre el álgebra booleana.

NOT: La operación NOT también podría ser llamada complemento y es un operador unario. Realiza la negación lógica de cada bit, es decir, invierte su valor. Por ejemplo, la operación NOT 1010 daría como resultado 0101.

AND: La operación AND, o conjunción lógica, funciona de forma similar a una multiplicación: sólo nos devolverá 1 si todas las entradas son 1, en el resto de casos devolvería 0. Es decir 0 AND 0 es igual a 0, 1 AND 0 es igual 0 y solo 1 AND 1 es igual a 1. Por ejemplo: 100111001011010100111010 AND 010110100001101111011000 = 000110000001000100011000. Cuando hacemos la operación AND la secuencia que dará como resultado no puede ser más larga que la mayor de las secuencias operadas.

OR: La operación OR, o disyunción lógica, dará como salida 1 siempre que una o más de sus entradas sean 1. Es decir, 1 OR 1 es igual a 1, 1 OR 0 es igual a 1 y solo 0 OR 0 es igual a 0. Por ejemplo: 1000 OR 0011 = 1011. Cuando hacemos la operación OR la secuencia que dará como resultado no puede ser más corta que ninguna de las secuencias operadas.

XOR: La operación XOR, u OR exclusivo, dará como salida 1 siempre que solo una de las dos entradas sea 1. Es decir, que 0 XOR 0 será igual a 0, 1 XOR 1 será igual a 0 pero 1 XOR 0 o 0 XOR 1 serán igual a 1. Por ejemplo 1010 XOR 1001 = 0011 Dado que es complicado revertir su resultado es muy utilizada en algoritmos de cifrado.

La instrucción With…End With de Visual Basic

Unas de las cosas más cómodas de la sintaxis de Visual Basic es la instrucción WITH…END WITH que, básicamente, nos permite acceder a los miembros de un objeto sin repetir su nombre constantemente.

La sintaxis básica sería la siguiente:

WITH Objeto
'lo que vayamos a hacer
'con sus miembros
END WITH

Dicho así no se entiende bien, pero con un ejemplo lo vemos claro. Tenemos aquí un objeto Mensaje y sus miembros son los valores que necesitamos para enviar un email:

 With Mensaje
   Set .Configuration = iConf
       .To = "correo@gmail.com"
       .From = "Donnie"
       .Subject = "Ejemplo with"
       .HTMLBody = correoHTML
       .Send
End With

Como podéis ver esta sintaxis nos ahorra escribir la referencia al objeto Mensaje antes de cada uno de sus elementos. Es a su vez cómodo para escribir y para leer el código.

Es posible anidar una sentencia WITH dentro de otra para acceder a un objeto interno, pero esto puede hacer nuestro código más difícil de leer.

With obVentana
    With .Etiqueta
        .Mensaje= "Esto es un aviso."
        .Fondo = Brushes.DarkSeaGreen        
    End With

    .Titulo = "VENTANA DE AVISO"
    .Show()
End With

Expresión regular en PHP para validar todo tipo de urls

Esta es una expresión regular que me he encontrado hoy modificando un antiguo proyecto en PHP y que podemos usar para validar tanto direcciones de email como direcciones url, recurriendo a la función preg_match() de PHP.

/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/

Investigando un poco he dado con el autor, o al menos con quien parece ser la primera fuente en publicar dicha expresión: Matthew O’Riordan. Aquí un link al hilo de StackOverflow donde lo explica.

Memoization: Acelerando funciones recursivas. Ejemplo con Javascript.

En su día hablamos aquí sobre la recursividad y sus “peligros“. Las funciones recursivas son muy costosas a nivel de recursos pues al llamarse a si mismas repiten varias veces el mismo paso ¿hay una solución?

Memoization (memorización) es una técnica consistente en almacenar los resultados de funciones muy costosas para devolverlos directamente en lugar de volver a calcularlos.

Por ejemplo, la siguiente función que ya vimos en un artículo anterior nos permitiría calcular un factorial con javascript:

function factorial(num)
{
    if (num < 0) {
        return 0;
    }
    else if (num == 0) {
        return 1;
    }
    else {
        return (num * factorial(num - 1));
    }
}

¿Podemos optimizar mucho esta función cacheando los datos? Podemos:

function factorial(num) {
    // inicializamos si es necesario
    if (!factorial.cache) {
        factorial.cache = {};
    }
    if (num == 0) {
        return 1;
    } else if (num in factorial.cache) {
    // si ya tenemos en cache el factorial de num, lo devolvemos
        return factorial.cache[num];
    } else {
    factorial.cache[num] = num * factorial(num - 1);
    return factorial.cache[num];
}
 

De esta forma nos ahorramos varias llamadas a la función pues simplemente devolvemos un valor almacenado en memoria. Esta no es una técnica exclusiva de Javascript, podemos utilizarla con otros lenguajes de programación. Javascript sí tiene la particularidad de tratar las funciones como un objeto más, eso nos permite por ejemplo definirle la propiedad cache en el ejemplo de arriba (en otros lenguajes deberíamos pasarle como parámetro a la función el array de valores o declararlo como variable global), esto también nos permite hacer que una función reciba como parámetro una función o devuelva como resultado otra función, lo que se conoce como higher-order function o función de orden superior. Sirviéndonos de esto podríamos declarar una función genérica para nuestro memoization:

const memoization = function(func){
    const cache = {};
    return (...args) => {
        const key = [...args].toString();
        return key in cache ? cache[key] : (cache[key] = func(...args));
    }
}

De esta forma podríamos definir nuestra función factorial() tal que así:

var factorial = memoization(function(num) {		
    return (num <= 1) ? 1 : num * factorial(num-1);
})

Añadir un PDF a un sitio web usando una etiqueta de HTML5

Existen varias formas de insertar un PDF dentro de un sitio web, una de ellas es usar alguna de estas etiquetas:

  • embed
  • object
  • iframe

Antaño solo teníamos la opción de usar la etiqueta iframe, dado que embed y object se añadieron para la especificación HTML5. En todo caso el procedimiento con las tres es el mismo: ponemos la URL del fichero PDF como valor del atributo src y definimos el tamaño mediante los atributos width y height:

<!--Ejemplos varios-->
<iframe src="http://rutaamipdf/fichero.pdf" width="95%" height="100%"></iframe>

<embed src="http://rutaamipdf/fichero.pdf" width="95%" height="100%"></embed>

<object src="http://rutaamipdf/fichero.pdf" width="95%" height="100%"></object>

¿Problemas? Pues sí, que con este método dependemos de que el navegador que está usando el usuario tenga incorporado algún visualizador de PDF. En algunos casos tiene que ser mediante un plugin externo, como en Chrome, en otros ya viene incluído por defecto en el propio navegador.

Cinco consejos a la hora de hacer scripts de Bash en Linux.

Llevamos unos días donde he hablado mucho de PowerShell y parece que nos estemos olvidando un poco del mundo Linuxero, así que hoy vamos a ver una serie de consejillos para hacer scripts con Bash en nuestro sistema Linux de forma más efectiva:

Usa comillas dobles a la hora de referenciar variables:

Trabajar con cadenas de texto con espacios puede ser problemático. A la hora de referenciar una variable para usar su valor es recomendable hacerlo poniéndola entre comillas dobles: evitará que la cadena se corte por el uso de espacios en blanco y también mejorará el rendimiento, evitando hacer rastreos de comodines innecesariamente. Si ejecutas este script lo verás:

empresas="Tecnológicas Camarasa SL"
echo "Sin comillas:"
echo
for nombre in $empresas; do
        echo "$nombre"
done
echo
echo "Con comillas:"
echo
for nombre in "$empresas"; do
        echo "$nombre"
done
exit 0

Si lo ejecutas verás como en el primer caso va a imprimir tres nombres, pues se confundirá con los espacios, mientras que en el ejemplo con comillas lo sacará en una sola línea respentado los espacios.

Forzar la salida del script en caso de error:

A veces un script puede seguir ejecutándose aunque un comando falle, y eso puede derivar en problemas más adelante. Con la siguiente línea podemos forzar la salida del script en caso de que un comando no funcione:

set -o errexit 

Forzar la salida del script en caso de usar una variable no declarada:

Como en el caso anterior, esto puede derivar en errores más graves más adelante, así que es recomendable que el script se detenga si se usa una variable que está sin declarar:

set -o nounset

Declara las constantes como readonly:

Las constantes en esencia son un variable con un valor estático. A la hora de declarar una constante en nuestro script, tanto por seguridad como por rendimiento, lo mejor es hacerlo con el atributo readonly, puesto que no va a vaciarse ni sobrescribirse el valor.

readonly fichero_host="/etc/hosts"
readonly pi=3.14159265359

Usa la sintaxis $(comando) en lugar del antiguo `comando` :

Si queremos asignar la salida de un comando a una variable antiguamente lo haríamos invocando al comando entre dos acentos. Hoy por hoy la sintaxis sería utilizando el comando entre paréntesis precedido por el carácter $, tal que así:

#Sintaxis antigua
usuario=`echo “$UID”`
#Sintaxis modernizada recomendada
usuario=$(echo “$UID”)