Estudiar Ingeniería Informática en la Universidad de Cádiz

¿Quieres estudiar Ingeniería Informática en la Universidad de Cádiz? Aquí te doy mi opinión acerca del Grado

Si lees esto es porque o bien tú o un conocido tuyo está pensando en estudiar el Grado en Ingeniería Informática por la Universidad de Cádiz (UCA) y quiere saber si hacerlo es una buena idea o no, porque ya estás estudiando ahí y te comienzas a plantear si hiciste o no una buena elección o, y me alegraría mucho, eres una profesora o profesor de la escuela interesado por leer una opinión real acerca del grado.

Como no hay una respuesta única o sencilla a esta pregunta que te haces, no puedo sino desgranar los puntos que a mi parecer son más importantes a la hora de realizar o reafirmar esta elección.

En primer lugar, y esto es muy importante, una Ingeniería es complicada; si no lo fuera, perdería algo de gracia. A una Ingeniería Informática se viene a aprender a pensar de forma abstracta. No se viene en exclusiva, ni mucho menos, a aprender a 'picar' código. No se viene a aprender React, Angular, Kotlin o Java. Se viene a aprender lógica, a estructurar tu cerebro de forma que sea capaz de afrontar cualquier problema. Se viene a aprender Álgebra Lineal o Matemáticas Discretas, que es lo que se exige para cualquier puesto en empresas como Google, Amazon o Microsoft. Sí my friend, esto no es un paseo. Hay otras opciones absolutamente respetables y totalmente necesarias como son los grados medios o superiores. De hecho, a mí me habría encantado haber hecho un superior en informática antes de entrar en la carrera, pero eso es otra historia sobre la que tal vez algún día escriba.

Teniendo esto claro, si de veras lo que buscas es ser un futuro elemento clave de una StartUp, un Ingeniero en Google o Microsoft, continua leyendo.

¿Sí? Entonces ya sabes que quieres la mitad del título de este post: 'Estudiar Ingeniería Informática'. Pero ¿cómo es hacerlo en Cádiz? Tiene sus pros y sus contras, como supongo que los tendrán el hacerlo en cualquier otra ciudad del mundo.

Pros

  • El equipo de profesores es bueno y está, en general, motivado: esto es algo vital para tu enseñanza
  • El contenido que se enseña es difícil y útil: asignaturas como EDNL, IP, DA, MD o PCTR te ayudarán muchísimo en tu futuro profesional, aunque no lo veas muy claro al principio
  • Saldrás preparado o preparada con conocimientos realmente útiles para muchas StartUps o incluso grandes empresas
  • La escuela es pequeña, lo que fomenta una cierta familiaridad con las y los compañeros
  • Hay muchas becas de movilidad (Erasmus, Santander, etc): si quieres hacer una estancia en el extranjero no tendrás demasiados problemas en comparación con otras Universidades en las que la competitividad es mucho mayor
  • Existen muchas opciones para realizar prácticas de empresa, y estas se pueden encontrar fácilmente a través de la plataforma Ícaro

Contras

  • La carrera es a mi parecer demasiado corta: no da tiempo a enseñar tecnologías como JavaScript, básicas en el mercado laboral
  • Se fomenta la realización de un máster para completar los conocimiento que pudieran no haberse tocado en la carrera (esto ocurre en otras Universidades españolas)
  • Sólo podrás hacer estancias internacionales en cuarto de carrera, y sólo podrás convalidar asignaturas optativas
  • La universidad no está en Cádiz, sino a unos dos kilómetros del Campus de Puerto Real: no es posible ir en bicicleta desde Cádiz y las conexiones con transporte público son deficientes y caras
  • Aunque termines y hagas tus prácticas en Cádiz, es muy probable que para seguir creciendo profesionalmente tengas que irte de la provincia

Me gustaría que este fuera un artículo vivo. Podría seguir escribiendo pros, contras, mis opiniones acerca de qué tecnologías deberían enseñarse en la carrera y cuáles no, qué optativas son las mejores en función a tus objetivos, etc, pero quiero dejarlo, por ahora, en este punto. Si tienes alguna duda puedes escribir un comentario, mandarme un email o escribirme a LinkedIn. Contestaré con gusto a tus preguntas y con ellas trataré de ampliar este artículo.

Gracias y suerte, Ernesto.

DON’T PANIC: Qué framework javascript escoger en 2018

Si estás a punto de comenzar un proyecto personal (como es mi caso) y la abrumadora cantidad de frameworks de desarrollo en Javascript te bloquea más que echa hacia delante: DON'T PANIC! Tienes suerte de estar ahí, agobiado o agobiada ¡pues eso significa que tienes elección! A nadie le va a importar qué tecnología uses, pues es un proyecto sólo para ti que podrá o no repercutir en tu futuro, y cualquiera de tus opciones serán buenas ya que si has oído hablar de ellas, es que funcionan, pues hay tantos miles de frameworks que el mero hecho de conocer el nombre de un  par de ellas quiere decir que miles de personas lo usan en su día a día.

Así que ya sea Angular, Vue o React; React Native, Weex o Vue-nativescript/React-nativescript, echa una moneda al aire, hazte un simple tutorial para ver cuál te resulta más amable o pregunta a un amigo que no sepa de informática qué nombre le gusta más, elige ese y no mires de nuevo hacia atrás.

Suerte 😉 - Y si te animas, escribe por aquí qué framework decidiste usar.

Calcular la altura de un árbol general en C++

El siguiente fragmento de código escrito en c++ calcula la altura de un árbol general de forma recursiva empleando plantillas de tipo T. Si bien esta pudiera no ser la forma más eficiente de realizar este procedimiento, es la que mejor escenifica el recorrido de la estructura de un árbol general. Tras el código he añadido un par de explicaciones, que se pueden completar con las dudas que dejes en los comentarios.

[code language="c"]
template <typename T>
template <typename T>
int Altura(const Agen<T> A, typename Agen<T>::nodo n){
if( n == Agen<T>::NODO_NULO)
return -1;
else{
// Tomamos al hijo de n
typename Agen<T>::nodo hijo = A.hijoIzqdo(n);
int max = -1;
// Recorremos al mismo y a todos sus hermanos
while(hijo != Agen<T>::NODO_NULO){
int aux = Altura(A, hijo);
if(aux > max)
max = aux;
hijo = A.hermDrcho(hijo);
}
return max + 1;
}
}
}
[/code]

A partir del nodo del árbol A, calculamos la altura, que se define como la longitud de la rama más larga que parte de n. Para aclararnos, la altura de un nodo hoja será 0 (-1 en el algoritmo) y la de la raíz será máxima. Si el nodo que encontramos es nulo, devuelve -1 para ajustar la solución, que de otra forma daría un entero de más. Si no, busca la máxima de las alturas entre el hijo izquierdo del nodo actual y su hermano derecho.

Modificar plantilla de Administración en Django 1.11 + (1.8+)

El siguiente snippet pretende ilustrar de forma directa y sencilla cómo funciona el sistema de plantillas que Django incorpora desde la versión 1.8, aplicado a la sobre-escritura de la plantilla de administración. Para detalles técnicos está la fabula documentación de Django.

Comencemos creando una carpeta de nombre templates, dentro de esta otra llamada admin, y dentro de admin un archivo al que llamaremos base_site.html. La estructura deberá quedar como sigue:

proyecto
*proyecto
*app1
*app2
*appn
*templates
**admin
***base_site.html

A continuación entra en la carpeta de plantillas de administración de Django en Github: https://github.com/django/django/tree/master/django/contrib/admin/templates/admin

Dentro de este directorio busca el archivo base_site.html. Ábrelo, copia el código que haya en su interior y pégalo en el archivo base_site.html que creaste en el paso anterior.

[code language="python"]
{% extends "admin/base.html" %}

{% block title %}Título de la página{% endblock %}

{% block branding %}

&amp;amp;amp;lt;h1 id="site-name"&amp;amp;amp;gt;&amp;amp;amp;lt;a href="{% url 'admin:index' %}"&amp;amp;amp;gt;Cabecera de la página&amp;amp;amp;lt;/a&amp;amp;amp;gt;&amp;amp;amp;lt;/h1&amp;amp;amp;gt;

{% endblock %}

{% block nav-global %}{% endblock %}
[/code]

Te quedará algo así, y aquí podrás modificar lo que tú quieras, pero para que los cambios aun se vean reflejados aun nos queda un paso más.

Entra en el archivo settings.py de tu proyecto y encuentra el bloque de código TEMPLATES. Dentro del diccionario DIRS, introduce la siguiente ruta:

os.path.join(BASE_DIR, 'templates'),

Deberá quedar algo como:

[code language="python"]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},

]
[/code]

Y ahora sí, al recargar tu página de administración podrás ver que los cambios han surtido efecto. A partir de esto, todo es probar a modificar lo que quieras a partir del proyecto Django original en GitHub.

La mejor forma de crear un entorno de desarrollo WordPress en Linux

Para la renovación de esta misma web tuve que desempolvar mis conocimientos en PHP, así como volver a repensar la forma ideal de instalar un servidor Apache en mi Ubuntu Gnome 14.04 con los mods necesarios para llevar a cabo las modificaciones que tenía en mente. No quería usar máquinas virtuales (docker, vagrant, virtualbox, etc) y XAMPP siempre me acaba dando algún que otro quebradero de cabeza al ejecutarlo en Linux.

Tras pesar y sopesar las infinitas opciones que gurús de todas las razas y religiones sugieren a lo largo ancho y hondo del ciberespacio, decidí acudir a un viejo conocido: Bitnami. Sabía desde hacía tiempo que esta empresa ofrecía una distribución con WordPress embebido, pero no había tenido la oportunidad de probarlo hasta ahora. ¡Y es una maravilla! Ni problema de permisos, bases de datos, versiones de php / apache / phpmyadmin... nada de nada, de la caja a la mesa. Es la opción con mayores parecidos que he encontrado a los virtual environments  de Python.

Te dejo aquí el link para que lo pruebes, y bueno querida lectora o lector, si sabes de alguna otra opción que me dejes en los comentarios, estaré encantado de echarle un ojo. Que pases un buen día 😉

Introducir texto/palabra por teclado vía terminal en Java

En este lenguaje encontramos múltiples formas de introducir texto por teclado mediante una terminal. A continuación expongo las principales mediante un simple código. Recomiendo usar JDK 1.7 o superior y una terminal, ya sea de un sistema Linux o Windows.

*Si decides ejecutar el código desde un IDE como eclipse, la última opción no funcionará ya que, como su nombre indica, está pensada para ser usada desde la terminal.

Si te queda alguna duda tras leerlo todo, siempre te quedarán los comentarios 😉

[code language="java"]
// En función de los métodos empleados, importar una u otra librería
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.Console;

public class Consola {
public static void main(String[] args) {
String texto = null;
// Librerías: import java.util.BufferedReader; y import java.io.IOException;
// Nota: Permite introducir espacios y saltos de línea
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Introduce algún texto: ");
try {
texto = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Texto introducido: " + texto);

// Da uso a import java.util.Scanner; A partir de Java 5
// Nota: Hay que cuidar el buffer IO. De tener varios sc.nextLine() este acabará desbordando.
Scanner sc = new Scanner(System.in);
System.out.print("Introduce algún texto: ");
texto = sc.nextLine();
System.out.println("Texto introducido: " + texto);

// Dependencia: import java.io.Console;
// Nota: Desde Java 6, la opción más recomendada para leer por consola
Console consola = System.console();
texto = consola.readLine("Introduce algún texto: ");
System.out.println("Texto introducido: " + texto);
}
}
[/code]

Fuente

[Solución] Error in runnabble ‘Creating Gradle model’

La solución al error:

SDK location not found. Define location with sdk.dir in the local.properties file or with ANDROID_HOME environment variable. See error log for detail.

, es muy simple. Tan sólo sigue los siguientes pasos:

  1. Busca el directorio donde esté instalado tu SDK. Por ejemplo: /home/ernesto/libGDX/sdk-android
  2. Entra en el directorio raíz de tu proyecto Gradle y localiza el archivo local.properties
    1. Si el archivo local.properties no existe, créalo y escribe dentro del mismo la ruta al directorio de tu SDK con el siguiente formato: sdk.dir=/home/ernesto/libGDX/sdk-android Una vez escrito, guarda el archivo y trata de volver a importar el proyecto.
    2. Si el archivo local.propierties sí que existe, edítalo con cualquier editor de textos como gedit o wordpad y añade o sobrescribe la siguiente línea:  sdk.dir=/home/ernesto/libGDX/sdk-android Sustituyendo /home/ernesto/libGDX/sdk-android por el directorio donde se encuentre tu SDK. Guarda el archivo y trata de importar nuevamente tu proyecto Gradle.

Esto es todo, si solucionaste tu problema te animo a que me lo comentes y si no, coméntalo también por aquí abajo y trataré de echarte un cable.

Cifrado César escrito en Java

El cifrado césar consiste en intercambiar las letras de un mensaje un número de posiciones determinadas por una clave. Más información de su historia y funcionamiento haciendo clic aquí.

El código que muestro más abajo es una versión del cifrado César tradicional pero empleando el alfabeto ASCII. Este alfabeto tiene 255 caracteres por lo que las posibilidades de cifrado y la dificultad para desencriptar se ven aumentadas. Sin embargo, las fórmulas que emplearemos son las mismas que se emplearon hace más de 2000 años, con una ligera variación:

*Se usa 27, porque en el alfabeto tradicional tenemos 27 caracteres.

Código ASCII

El código tiene dos versiones, una sin optimizar en la que se desglosa el proceso línea por línea y otra optimizada pero algo menos legible.

Ambos scripts están pensados para ser ejecutados desde una terminal de un sistema operativo en el que se encuentre instalado el JDK 7 u 8 (clic aquí para instalarlo en Linux).

Si tienes algún problema con la entrada de texto en Java haz clic aquí.

Si encuentras bugs, se te ocurren ideas para mejorar el código o lo que sea, te invito a expresarte en los comentarios.

Versión primera

[code language="java"]
/**
* Created by erwol on 03/03/2016 at 12:39
* For further information visit http://www.archecode.org
*/
import java.util.Scanner;
import java.io.Console;
public class Cesar {
private static Scanner lee = new Scanner(System.in);
public static void main(String args[]){
int op = -1;
String texto = null;
Console consola = System.console();
int clave = 0;
while(op != 0){
System.out.print("ntCIFRADO CÉSARn0.- Salirn1.- Cifrarn2.- Descifrarn&gt; ");
op = lee.nextInt();
switch(op){
case 0:break;
case 1:
System.out.printf("1. Introduzca el texto a cifrarn&gt; ");
texto = consola.readLine();
System.out.printf("2. Introduzca la clave con la que se codificará el texton&gt;");
clave = lee.nextInt();
System.out.println("3. Cadena cifrada con clave = " + clave + " -&gt;" + cifrar(texto, clave) + "&lt;-");
break;
case 2:
System.out.printf("1. Introduzca el texto cifradon&gt; ");
texto = consola.readLine();
System.out.printf("2. Introduzca la clave con la que codificó el texton&gt; ");
clave = lee.nextInt();
System.out.println("3. Cadena cifrada con clave = " + clave + " -&gt;" + descifrar(texto, clave) + "&lt;-");
break;
default:System.out.println("3. Ha introducido una opción no válida. Pruebe de nuevo.");
}
}
}

static String cifrar(String original, int clave){
// Inicializado con el tamaño de la cadena original. STRING SON INMUTABLES!
StringBuilder cifrado = new StringBuilder(original.length());
int valorASCII = 0;
for(int i = 0;i &lt; original.length(); i++){
// 1 Guardamos el valor ASCII (31 - 126) del caracter número i
valorASCII = (int)(original.charAt(i));

// 2 Aplicamos la fórmula
valorASCII = valorASCII + clave % 255;

// 3 Añadimos el caracter cifrado
cifrado.append((char)(valorASCII));
}
// 4 Devolvemos la conversión de StringBuilder a String
return cifrado.toString();
}

static String descifrar(String original, int clave){
// Proceso inverso del cifrado
StringBuilder descifrado = new StringBuilder(original.length());
int ASCIIcifrado = 0, n = 0;
for(int i = 0;i &lt; original.length(); i++){
ASCIIcifrado = (int)(original.charAt(i));
ASCIIcifrado = ASCIIcifrado - clave % 255;
descifrado.append((char)(ASCIIcifrado));
}
return descifrado.toString();
}
}
[/code]

Versión segunda

[code language="java"]
/**
* Created by erwol on 04/03/2016 at 13:55
* For further information visit http://www.archecode.org
*/
import java.util.Scanner;
import java.io.Console;
public class Cesar_simplificado {
private static Scanner lee = new Scanner(System.in);

public static void main(String args[]){
int op = -1;
String texto = null;
Console consola = System.console();
int clave = 0;
while(op != 0){
System.out.print("ntCIFRADO CÉSARn0.- Salirn1.- Cifrarn2.- Descifrarn&gt; ");
op = lee.nextInt();
switch(op){
case 0:break;
case 1:
System.out.printf("1. Introduzca el texto a cifrarn&gt; ");
texto = consola.readLine();
System.out.printf("2. Introduzca la clave con la que se codificará el texton&gt;");
clave = lee.nextInt();
System.out.println("3. Cadena cifrada con clave = " + clave + " -&gt;" + cifrar(texto, clave) + "&lt;-");
break;
case 2:
System.out.printf("1. Introduzca el texto cifradon&gt; ");
texto = consola.readLine();
System.out.printf("2. Introduzca la clave con la que codificó el texton&gt; ");
clave = lee.nextInt();
System.out.println("3. Cadena cifrada con clave = " + clave + " -&gt;" + descifrar(texto, clave) + "&lt;-");
break;
default:System.out.println("Ha introducido una opción no válida. Pruebe de nuevo.");
}
}
}

static String cifrar(String original, int clave){
StringBuilder cifrado = new StringBuilder(original.length());
for(int i = 0;i &lt; original.length(); i++)
cifrado.append((char)((int)(original.charAt(i)) + clave % 255));
return cifrado.toString();
}

static String descifrar(String original, int clave){
StringBuilder descifrado = new StringBuilder(original.length());
for(int i = 0;i &lt; original.length(); i++)
descifrado.append((char)((int)(original.charAt(i)) - clave % 255));
return descifrado.toString();
}
}
[/code]