Alters

Mundo exterior: Vectores de Rn - Parte I

Buenas!

Traemos una entrada "light", de domingo...

Dejo, como siempre, la zona de temario que veremos:


  1. Matrices y vectores 
    1. Operaciones básicas
      1. Suma
      2. Resta
      3. Multiplicación
    2. Propiedades
    3. Otras operaciones
      1. Traza
      2. Simétricas
      3. Antisimétricas
    4. Determinantes
      1. Explicación
      2. Determinantes de orden 3
      3. Determinantes de orden 4
      4. Propiedades
      5. Representación geométrica de determinantes de orden 3
    5. Rango
    6. Inversas
    7. Uso de parámetros
    8. Vectores de Rn
      1. Tipos
      2. Operaciones básicas
        1. Suma
        2. Producto escalar
      3. Dependencia / independencia lineal
      4. Subespacios de Rn
      5. Familias generadoras y bases
      6. Otras operaciones
        1. Norma euclidiana
        2. Producto de vectores
        3. Producto vectorial (restringido a R3)
    9. Sistemas de ecuaciones lineales
      1. Tipos


1.8. Vectores de Rn

  1.8.1. Tipos

Existen dos tipos de vectores de Rn (léase "R" como el conjunto de números reales).

 - Listas ordenadas: (x, y, z)
 - Listas desordenadas: {x, y, z}

Es posible encontrar vectores en ambas formas, aunque la más común es la primera (vectores ordenados, como los que casi siempre salen; una matriz 1x3 es un vector).

  1.8.2. Operaciones básicas

    1.8.2.1. Suma

La suma de vectores se hace tal como se hace la suma de determinantes. Componente a componente.

Si no recuerdas cómo se suman determinantes/matrices, aquí puedes verlo.

    1.8.2.2. Producto escalar

El producto escalar, definido como:

n(x, y, ..., z)

Se calcularía como:

(nx, ny, ..., nz)

  1.8.3. Dependencia lineal

Dos vectores son linealmente dependientes (L.D) si y solo si (sii):


E a1, …, an (no todos = 0) |Si aivi = 0

Por otra parte, son L.I. sii


Si aivi = 0 (todos a = 0)

Estos conceptos están relacionados con el rango. Definimos el rango con el siguiente ejemplo:

En "R" caben "n" vectores independientes. El rango del vector {v1, …, vn} es el número máximo entre ellos que son L.I.


  1.8.4. Subespacios de Rn

"F" es un subespacio de Rn sii "F" es un espacio vectorial y pasa por el origen, es decir (adjunto captura):



Dado un subespacio vectorial conocido, se conocen todas sus combinaciones lineales (anteriores propiedades).

Y bien, hasta aquí la entrada...

Se que los apuntes son algo liosos... pero están más liados aún en mis papeles... pero es solo al principio, luego todo se expone más claro.

En fin, poco a poco vamos avanzando. La próxima entrega sera un "break tecnológico", típico de cuando adquiero un nuevo gadget :-)

Saludos, y...

¡Hasta la próxima!

¡Novedades!


Buenas!

Hace unos días os dije que se avecinaban cambios... pues bien, uno de ellos está listo.

He añadido una barra de menús en los que (intentaré) agrupar las entradas del blog por temáticas.

Ahora, cuando queráis seguir los proyectos, o ver el plan que hay para algún proyecto (como el de matemáticas), podréis verlo con un solo click.

Hablando del proyecto actual, veréis que el planing completo está puesto en su correspondiente sección (Mundo exterior); como los apuntes ya los tengo, puedo planificar todo el contenido... serán 27 entradas, lo que da para largo (será la serie más larga del blog hasta el momento)...

Y bien, queda otro cambio pendiente ahí, a ver qué es lo que pasa...

De momento, iré preparando la próxima entrada, así como pensando qué mini-serie hacer entre el tema 1 y el tema 2

Como siempre, saludos, y...

¡Hasta la próxima!

Mundo exterior: Matemáticas - Tema 1: Determinantes, rangos, inversas y parámetros


Buenas!

Otra entrada más volvemos a las matemáticas; esta vez veremos determinantes, rangos, inversas y el uso de parámetros.

Como dije, aquí el índice con lo que veremos:

  1. Matrices y vectores 
    1. Operaciones básicas
      1. Suma
      2. Resta
      3. Multiplicación
    2. Propiedades
    3. Otras operaciones
      1. Traza
      2. Simétricas
      3. Antisimétricas
    4. Determinantes
      1. Explicación
      2. Determinantes de orden 3
      3. Determinantes de orden 4
      4. Propiedades
      5. Representación geométrica de determinantes de orden 3
    5. Rango
    6. Inversas
    7. Uso de parámetros
    8. Vectores de Rn
      1. Tipos
      2. Operaciones básicas
        1. Suma
        2. Producto escalar
      3. Dependencia / independencia lineal
      4. Subespacios de Rn
      5. Familias generadoras y bases
      6. Otras operaciones
        1. Norma euclidiana
        2. Producto de vectores
        3. Producto vectorial (restringido a R3)
    9. Sistemas de ecuaciones lineales
      1. Tipos


4. Determinantes
  4.1. Explicación

Un determinante es un número, que puede ser expresado bien en forma de número, o bien en la forma de "operador" (así como, por ejemplo, "5" se puede representar como "5" o como "2+3").

El valor de un determinante representa el área de la suma de todos los vectores que lo conforman, determinando el signo de dicho valor en que dirección "giran" los vectores.

Dejo un escaneo de un ejemplo de mis apuntes:





























 4.2. Determinantes de orden 3

Los determinantes de orden 3 se calculan mediante "Sarrus". Esto es:

"Sumatorio del productorio de la diagonal principal y paralelas menos el sumatorio del productorio de la invertida a la diagonal principal y sus paralelas".

Un ejemplo:


           1  2  3
    A=  4  5  6
           7  8  9

|A| = (1*5*9+4*8*3+2*6*7)-(3*5*7+2*4*1+6*8*9)=45+96+84-105-8-432=-320


  4.3. Determinantes de orden 4

Para resolver un determinante de orden 4, podemos aplicar una serie de "meta-propiedades" de los determinantes, que nos vienen a decir que si combinamos de manera lineal las filas o columnas de un determinante, el resultado no varía (lo mismo pasa con el orden de las mismas).

De esta manera, podemos combinarlas (matemáticas de bachillerato) para obtener una fila (la primera, preferentemente) que conste de un número (no 0) y el resto todo de 0.

El resultado de este determinante sería el resultado de multiplicar el resultado del determinante complementario (es decir, el determinante que queda si eliminamos del mismo la fila "i" y la columna "j", siendo el elemento aij) por dicho elemento. Es decir:


       a b c d
A = e f g h
       i j k l
       m n o p

Transformamos:

      a’ b’ c’ d’
A= 0 f’ g’ h’
      0 j’ k’ l’
      0 n’ o’ p’

|A| = a’B


      f’ g’ h’
B= j’ k’ l’
     n’ o’ p’


  4.4. Propiedades

Los determinantes tienen las siguientes propiedades:

- Si multiplicamos una fila por "n", el resultado se multiplica por "n".
- Si se intercambia una fila de sitio, el determinante cambia de signo.
- A una fila, sumada otra fila multiplicada por "n", el determinante no cambia.

Todas ellas son aplicables tanto a filas como a columnas.

  4.5. Representación geométrica de determinantes de orden 3

Como explicaba al principio, el determinante representa un área (o volumen e 3 dimensiones, volumen en 4 dimensiones, etc).

Dejo una representación geométrica de un determinante de orden 3:



















5. Rango

Definimos el rango como el número de filas/columnas linealmente independientes en un determinante.

Para obtener el número de filas/columnas linealmente independientes (L.I.) basta con triangular con 0 el determinante, y sobre la marcha veremos el rango del mismo.

6. Inversas

Para calcular inversas usaremos el método de las dos triangulaciones:

 - Triangulas por abajo con 0
 - Triangulas por arriba con 0
 - Conviertes en I

Todo esto partiendo de una matriz/determinante "doble". Adjunto proceso:






















7. Uso de parámetros

El uso de parámetros en el estudio de rangos de matrices es bastante extenso. Para ello debemos aislar los casos "problemáticos" mediante el uso de las anteriores "meta-propiedades" mencionadas, pero teniendo en cuenta una regla especial:

- NO multiplicar (ni dividir) por parámetros NUNCA la fila sustituída.

Es decir:

2*fila1 + 1*fila2 => está bien
a*fila1 + 4*fila2 => está bien
23*fila1 + 2a*fila2 => MAL

Y con esto terminamos la entrada 2/5 del primer tema de matemáticas. La próxima entrada veremos hasta los subespacios de Rn.

Como siempre, saludos, y ¡Hasta la próxima!



Mundo exterior: Matmáticas - Tema 1: Matrices


Buenas!

Empezamos con las matemáticas, concretamente con el primer tema (matrices y vectores).

Este tema durará 5 entradas. En cada una os pondré el índice del tema y la parte que vamos a tratar de él.

  1. Matrices y vectores 
    1. Operaciones básicas
      1. Suma
      2. Resta
      3. Multiplicación
    2. Propiedades
    3. Otras operaciones
      1. Traza
      2. Simétricas
      3. Antisimétricas
    4. Determinantes
      1. Explicación
      2. Determinantes de orden 3
      3. Determinantes de orden 4
      4. Propiedades
      5. Representación geométrica de determinantes de orden 3
    5. Rango
    6. Inversas
    7. Uso de parámetros
    8. Vectores de Rn
      1. Tipos
      2. Operaciones básicas
        1. Suma
        2. Producto escalar
      3. Dependencia / independencia lineal
      4. Subespacios de Rn
      5. Familias generadoras y bases
      6. Otras operaciones
        1. Norma euclidiana
        2. Producto de vectores
        3. Producto vectorial (restringido a R3)
    9. Sistemas de ecuaciones lineales
      1. Tipos
1. Operaciones básicas:
  1.1. Suma

La suma de matrices se puede expresar como la suma de los elementos análogos de sendas matrices a sumar. Es decir, imaginad la siguiente suma:

(1 3 5) + (3 1 9)

Las de arriba son dos matrices de 1x3 (o 3x1... siempre me lío con esto! jajaja). El resultado lo podríamos definir como:

(1+3 3+1 5+9)

o lo que es lo mismo

(4 5 14)

  1.2. Resta

La resta de matrices se basa en el mismo método que la suma, pero en este caso se restarán los elementos correspondientes.

  1.3. Multiplicación
    a) Escalar

Multiplicar un escalar por una matriz equivale a multiplicar cada elemento de la matriz por dicho escalar. Es decir:

2*(1 3 5) = (2 6 10)

    b) Producto de matrices

La definición formal de la multiplicación de dos matrices, "A" y "B" es que dan como resultado una tercera matriz "C" cuyos elementos responden a la siguiente fórmula:

Cij  = S aik bkj

Siendo "k" el rango de todos los posibles valores de "A" o "B"

Pongamos un ejemplo:

A = 3 2 1
       4 5 7

       2 5 7
B = 3 8 4
       1 7 9

AB = C

C23 = S a2kbk3 = 111 [(4*7+5*4+7*9)]



La matriz completa "C", sería:

       13   38    38
C = 30  109  111


2. Propiedades 

Existen cuatro propiedades básicas de las matrices:

a) n(A+B) = nA + nB [n = escalar; A, B = matrices]
b) (n+m)A = nA + mA [n, m = escalares; A = matriz]
c) A(B+C) = AB + AB [A, B, C = matrices]
d) IA = AI = I [A, I = matrices; I = matriz identidad]

Por otra parte, clarificando la última propiedad, hay una que no se "hereda" de la multiplicación: la propiedad conmutativa.

No es lo mismo AB que BA. Y esto se debe principalmente a dos cosas: la posible incompatibilidad de rangos y la posible alteración de rangos. Vamos a explicarlo:

a) Incompatibilidad:

Imaginad la matriz A, de dimensiones 4x7; por otra parte, la matriz B tiene dimensiones de 7x3.

Si efectuamos AB, obtendríamos una matriz de 4x3; si intentamos efectuar BA, nos encontramos con que no se puede (para efectuar una multiplicación, las dimensiones tienen que ser nxm, * mxo, cosa que no se cumple en este caso).

b) Alteración

¿Y si A es una matriz de 4x7 y B una de 7x4? Sería factible tanto AB como BA, pero si estudiamos el caso:

 - AB: resultado de una matriz 4x4 (4x7 * 7x4)
 - BA: resultado de una matriz 7x7 (7x4 * 4x7)

Ahí vemos como se alteran las dimensiones (y por tanto no pueden ser iguales).

Se entiende, por tanto, que no es lo mismo AB que BA, por lo que la propiedad conmutativa de la multiplicación de matrices queda desestimada.

3. Otras operaciones
  3.1. Traza

La traza de una matriz responde a la siguiente fórmula:

TA = Snk=1 akk [TA = Traza de A; akk = elemento (k, k) de A]

En otras palabras, consiste en sumar los elementos de la diagonal que corre de la esquina superior izquierda a la inferior derecha (conocida como diagonal principal), correspondiente a los índices donde i=j [(1, 1), (2, 2), (3, 3)...].

Para que una matriz pueda tener traza, ha de ser cuadrada (mismo número de filas que de columnas).


  3.2. Transpuestas

Transponer una matriz consiste en invertir el orden de todos sus elementos, de manera que:

Cij = Aji

Como ejemplo, podríamos tener:

       3 2 1
A = 4 5 7

         3 4
 At = 2 5
         1 7

  3.3.Simétricas 

Una matriz simétrica es aquella cuya transpuesta es la misma que la "original".

  3.4. Antisimétricas

Una matriz antisimétrica es aquella cuya transpuesta es equivalente a la negativa (no inversa) de la "original".

Su diagonal principal es 0.


Con esto finalizamos la primera entrega de este curso de matemáticas. Comentar que me había dejado el apartado de "Transpuestas" en el índice...

La próxima entrega veremos la segunda parte de este primer tema.

Saludos, y

¡Hasta la próxima!

Mundo exteriror: Matemáticas - Preámbulo

Buenas!

Vamos a adentrarnos en un mundo ajeno a la informática (pero que podemos relacionar): las matemáticas.

La verdad es que hubo una temporada que no me gustaban... pero en la universidad les tomé de nuevo mucho cariño, y es que volver a hacer mates después de 4 años y ver que te sale mucho mejor que antes (gracias al pensamiento pragmático que otorga llevar algo más de 4 años programando de manera "oficial") anima bastante.

Es por eso que decidí compartir con vosotros mis apuntes de matemáticas. Son de la carrera de química, de primer año.

Y bueno, ésta es otra de mis aficiones (más abandonada, espero avanzar algún día)... de ahí el fondo del blog.

Así, os dejo un índice de lo que veremos:

  1. Matrices y vectores
  2. Funciones de diversas variables
  3. Integrales dobles
  4. Integrales triples
  5. Integrales de línea
  6. Espacios vectoriales
  7. Ecuaciones diferenciales
  8. Anexo

Y en concreto, el primer tema:

  1. Matrices y vectores
    1. Operaciones básicas
      1. Suma
      2. Resta
      3. Multiplicación
    2. Propiedades
    3. Otras operaciones
      1. Traza
      2. Simétricas
      3. Antisimétricas
    4. Determinantes
      1. Explicación
      2. Determinantes de orden 3
      3. Determinantes de orden 4
      4. Propiedades
      5. Representación geométrica de determinantes de orden 3
    5. Rango
    6. Inversas
    7. Uso de parámetros
    8. Vectores de Rn
      1. Tipos
      2. Operaciones básicas
        1. Suma
        2. Producto escalar
      3. Dependencia / independencia lineal
      4. Subespacios de Rn
      5. Familias generadoras y bases
      6. Otras operaciones
        1. Norma euclidiana
        2. Producto de vectores
        3. Producto vectorial (restringido a R3)
    9. Sistemas de ecuaciones lineales
      1. Tipos
Iré plasmando mis apuntes tal cual, con alguna anotación, incluso escaneados directos (de ejercicios y demás).

En principio, ya que la asignatura duró medio año, esto puede alargarse, así que entre tema y tema haremos pausas para hablar de otras cosas...

Así, en la próxima entrada entraremos directamente con las matrices.

Saludos y ¡Hasta la próxima!

Tips & Tricks: Overlay de eventos en JavaScript (II)

Buenas!

Vamos a ver rápidamente cómo tratar el solapamiento de eventos con AJAX...

Y es que AJAX puede resultar difícil de usar... ya que muchas veces se necesita de un elemento existente para que funcione bien...

Para empezar con los ejemplos, supondremos la siguiente llamada a función:

doAjax(url, query, getXML, divToChange, ev);

siendo los dos parámetros la URL completa; el tercer parámetro indica (con 1 o 0) si el resultado es o no XML.

El valor de divToChange es el id del div (o elemento) que queramos cambiar. Por otra parte, "ev" hace referencia a si el resultado ha de ser evaluado.

Pues bien, si "divToChange" hace referencia a un id inexistente, habrá un fallo en AJAX, por lo que siempre debemos comprobar que el elemento existe.

¿Y puede ser que no exista?

Pues, sí. Si hacemos varias cargas seguidas con AJAX/JS, puede ser que, al ser AJAX paralelo, intente acceder a un id que todavía no existe.

Para que esto no pase tenemos varias opciones:

a) Esperar un tiempo determinado
b) Evitar que AJAX sea paralelo

La primera opción tiene sus ventajas, pero posee un inconveniente que, para mí, es bastante obvio: dependiendo de la conexión que poseamos tardará un tiempo u otro.

Así, que, siempre que sea factible, al hacer varias cargas con AJAX deberíamos usar AJAX secucuencial.

Pero esto no es todo; si tenemos muchas llamadas AJAX seguidas, podemos hacer que AJAX pierda la petición y quedarnos sin resultado.

Es decir, suponed algo así:

for(i=0;i<20;i++){
  doAajax(url,query,0,'contenido'+i,0);
}

Al ser un bucle sin más, nuestro Request perderá las peticiones (se solaparán), saliendo solo el resultado de la última.

Para no perder las peticiones podríamos esperar, como en el primer caso... pero ¿cuánto?

Pues... un tiempo indefinido, el justo para que la petición termine.

Para ello haremos uso de "setTimeout", cuyo uso es:

window.setTimeout(function(){sentencia_a_ejecutar}, tiempo);

En nuestro caso, debemos embeber la llamada. Es decir, pasaríamos el código anterior al siguiente:

for(i=0;i<20;i++){
  doAjaxTimed(url,query,0,'contenido'+i,0);
}

function doAjaxTimed(url,query,getXML,divToChange,eval){
  window.setTimeout(function(){doAjax(url,query,getXML,divToChange,eval)}, t);
}

Y, , usamos "t", sin definir... con esto tardará lo que tenga que tardar... y los eventos no se solaparán.

Ahora vamos a otro caso de solapamiento de eventos:

Imaginad que queremos hacer el típico sistema de "select" para elegir país y ciudad. Al elegir un país cambian las ciudades mediante AJAX, y los países se cargan a posteriori con AJAX, de manera que:
<div class="decision">
  <select id="paises"><option value="0"<Seleccione</option></select>
  <select id="ciudades"><option value="0">Seleccione</option></select>
</div>
<script type="text/javascript"&gt;doAjax(url,query,0,"paises",0);//carga de paises</script>
Esto funciona a las mil maravillas para cargar las ciudades. Luego veremos el resto... pero ahora surge la duda: ¿Y si cargamos todo esto previamente con un AJAX?

Entonces, el script no se ejecuta, ya que no evaluamos ninguna sentencia. Tocará pensar algo...

¿Un timer? Pasa lo de siempre, debemos esperar...

He aquí una solución que me gusta más: un handler. Hacemos así:


<div class="decision">
  <select id="paises" onmouseover="carga();"><option value="0"<Seleccione</option></select>
  <select id="ciudades"><option value="0">Seleccione</option></select>
</div>

Y definimos en un fichero externo la función "carga()":

function carga(){
  if(document.getElementById('paises').options.length &gt; 1){
    return false;
  }

  doAjax(url,query,0,'paises',0);
  return false;
}

Y así, al tener el ratón por encima (antes de hacer click) se cargarán los países, sin que se note...

Y con esto podemos tener algo más controlado nuestro JS y AJAX.

Como final me gustaría añadir que estas entradas han sido algo raras y escasas, lo se... estoy demasiado liado con todo... a ver si los futuros cambios me sirven para ir a mejor!

Y como siempre,

¡Hasta la próxima!

Tips & Tricks: Overlay de Eventos en JavaScript

Buenas!

Se avecinan cambios por aquí... de momento todo queda tal como está, pero nunca se sabe...

En fin, vamos a ver un poco el tema del solapamiento de eventos en JavaScript.

Y es que mucho se ha de tener en cuenta a la hora de hacer una serie de funciones JavaScript, ya que, en ocasiones, puede que no suceda aquello que esperamos...

Y es que muchas veces lo que esperamos no es exactamente lo mismo que el navegador "interpreta"... y uno de estos casos es el solapamiento.

Hay varios tipos de solapamiento en JavaScript (realmente se le llama "solapamiento"?). Empezaremos con los básicos, y luego iremos con el tema de AJAX (JavaScript y XML Asíncronos).

¿Qué es el solapamiento?

Supongamos que tenemos esta estructura HTML:

<body>
  <div id="contenido">¡Haz Click!</div>
  <div id="contenedor"></div>
</body>

Y supongamos que queremos que al hacer click sobre el texto (el div, en realidad) se muestre un texto en "contenedor".

Podríamos hacer algo así:

<body>
  <div id="contenido" onclick="document.getElementById('contenedor').innerHTML = 'contenido';>¡Haz Click!</div>
  <div id="contenedor"></div>
</body>


Hay muchas maneras para hacer lo que queremos; podríamos, por ejemplo, crear un nuevo "div"  desde cero (de "la nada") y ponerle el texto, pero esto (me da la sensación) que sería más costoso.

Así, lo que hacemos en el código de arriba es añadir un handler (manejador) que saltará cuando hagamos click (en inglés "on click", y todo junto "onclick") es editar el html interno del elemento con id "contenedor".

Ahora vamos a dejarlo todo por separado, el JS por un sitio y el HTML por otro:

[div]
<script type="text/javascript">
function muestra(){
 document.getElementById('contenedor').innerHTML = 'contenido';
 return false;
}
</script>
<body>
  <div id="contenido" onclick="muestra();">¡Haz Click!</div>
  <div id="contenedor" ></div>
</body>


Esta función no tiene mucho sentido, pues es muy "particular". Así que la vamos a hacer de ámbito general para poder usarla por más de un elemento:

function muestra(elemento,texto){
  document.getElementById(elemento).innerHTML = texto;
  return false;
}

Bien, ahora nuestro handler sería:

onclick="muestra('contenedor', 'Esto es texto');"

Ahora podríamos hacer que cualquier "div" mostrase cualquier texto... es más general.

Sigamos haciendo nuestra "web"... ahora queremos que al pulsar otro elemento que no sea el div "contenido" el texto se oculte.

Para denotar "cualquier elemento", podemos usar el body mismo... ya que éste contiene todos los elementos.

<body onclick="document.getElementById('contenedor').innerHTML = '';"> ** nótese que son dos comillas simples, un ";" y unas comillas dobles **

o lo que es lo mismo:

<body onclick="muestra('contenedor', '');">

Y vamos a probar, y... ¡OH! nuestra "web" no funciona!

Como decía antes, sí funciona, solo que no como esperábamos.

¿Y qué ha pasado? Se han solapado dos eventos JavaScript.

Vamos a explicar esto un poco: imaginad una web como algo tridimensional... (como lo hace FireFox cuando editamos el diseño OTF :-P )

Entonces, nuestra "web" sería algo así (lo haría más bien hecho, pero es tarde y no me apetece mucho jugar con las perspectivas del CorelDraw X5...):



Supongamos que el cubo verde es "contenido", el rojo "contenedor" y lo azul es "body". Al hacer click en "contenido" saltará el evento que pone el texto, pero a su vez estamos haciendo click sobre "body", por lo que vuelve a saltar el evento, borrando el texto...

Es decir, así como los programas tienen una pila de llamadas donde se apilan las llamadas de funciones, para saber a qué dirección de memoria volver cuando acabe la función actual, JS tiene una pila eventos, de manera que parece que no funcione, pero en realidad va todo tan rápido que parece que no funcione...

Entonces, ¿Cómo hacemos para que funcione como queremos?

Analicemos la situación: al hacer click en "contenido", la función es llamada dos veces, mientras que en cualquier otro sitio solo es llamada una vez.

Por tanto, podemos definir las siguientes cláusulas:

 - Si la función se ha de mantener, se harán X clicks (2, en este caso)
 - Si no, se harán solo Y clicks (1 en este caso).

Bien, vamos a hacer un poco más grande nuestro JS:

<script type="text/javascript">
var max = 2;

function muestra(elemento, contenido, flag){
  max--;

  if(flag && max > 0){
   document.getElementById(elemento).innerHTML = '';
  }else{
    if(!flag){
        document.getElementById(elemento).innerHTML = contenido;
    }
  }

  if(max == 0 || flag){
    max = 2;
  }
}
</script>

Entonces, vamos a ver:

Primero hacemos un contador global, con valor 2. Luego hemos modificado la función para que acepte un parámetro adicional (booleano), para diferenciar la llamada del div de otras.

Entonces, en "contenido" haremos:

onclick="muestra('contenedor', 'texto', false);"

y en body:

onclick="muestra('contenedor', 'texto', true);"

Así, al hacer click sobre el div, pasará lo siguiente (suponiendo una primera ejecución):


  • Parámetros de entrada: "contenedor", "texto", "false"
  • max disminuye (max = 1)
  • Entra en el "else"
  • Se escribe el texto
  • No entra en el if
  • Devuelve la llamada a la pila
  • Llamada desde Body: "contenedor", "", "true"
  • max disminuye (max = 0)
  • Entra en el else
  • NO entra en el if (y por tanto no se modifica nada)
  • Entra en el segundo if (max = 2)
¡Bien!, el texto ya se queda. Si llamamos directamente desde body:

  • Parámetros: "contenedor", "texto", "true"
  • max disminuye (max = 1)
  • Entra en el if
  • Vacía el elemento
  • Entra en el segundo if (max = 2)
Y hemos evitado que, al solaparse, se produzca un borrado.

En la próxima entrada, veremos solapamientos con AJAX, y cómo solucionarlos de varias maneras.

Más adelante (la siguiente entrada a la de AJAX), entraremos en un mundo algo diferente: Matemáticas.

Ya veremos cómo acaba esta aventura.

Saludos, como siempre, y...

¡Hasta la próxima!


Aventuras de DoHITB: parte III (b) - Final

Buenas!

Por fin llega el fin de semana, y tras una semana agotadora (13h/día trabajando) por fin me puedo relajar un poco y acabar (por fin) mi pequeña aventura.

Antes me gustaría comentaros que he avanzado mi proyecto de PPHP como parte del desarrollo en el que estoy metido. También tengo otra cosilla por ahí relacionada con una base de datos y PHP... algo así como un generador de objetos previamente definidos (aunque podría combinarlo con mi proyecto de PPHP y hacer algo verdaderamente paranóico...).

También aprendí a resolver un conflicto que siempre había tenido con JavaScript... esto lo veremos en la próxima entrada.

En fin, volvamos a la parte final de mi historia:

Como os comenté, vamos a ver Threads y peticiones HTTP.

Para usar estas características, nos apoyaremos en funciones ya establecidas de varios paquetes de JAVA. De todas maneras, vamos a ver cómo funcionan un poco por encima los Thread y las peticiones.

Thread

Un "thread" (hilo) es un fragmento de programa, un proceso si queréis, que se ejecuta de forma paralela al proceso (hilo) principal. Es decir: normalmente todos nuestros programas con concurrentes (un solo hilo); no obstante algunas partes podrían hacerse en paralelo (a la vez), y muchas veces no lo hacemos.

Un ejemplo sencillo: imaginad que "diseñamos una persona". Si usaramos programación concurrente, mientras respirara no podría parpadear (por ejemplo), por lo que tendríamos que hacer un bucle para que fuera respirando y pestañeando (incluso podríamos hacer que lo fuera haciendo "a trozos" para que pareciera que lo hace a la vez).

Sin embargo, en realidad lo que pasa es que son dos cosas completamente independientes. Pues sería como hacer un hilo (Thread) para la respiración y otro para el parpadeo.

Y bien, para usar concurrencia en programación tenemos que tener muy en cuenta el orden de procesos, ya que no sabemos a ciencia cierta qué hilo irá "más rápido".

¿A qué me refiero con eso? Con un ejemplo se ve mejor. Supongamos que quiero hacer lo siguiente::

a = 10;
b = 20;
c = 30;
d = 40;
e = 50;
f = 60;
g = 70;
h = 80;
i = 90;
j = 100;
k = 110;
c = a+b;
d = a-b;
d = d+b
e  = 100-d;
f = e*d*a;
c = c+100;
g = c+a;
h = c+b;
i = g*h;
j = i/f;
k = j+i/f;

He querido marcar un poco cosas que se pueden hacer concurrentemente  (del mismo color) y cosas que se pueden hacer paralelamente (diferentes colores). De esta manera, podríamos calcular "d" y "g" al mismo tiempo, ya que son independientes (no tienen datos en común); mientras que para generar "f", tenemos que tener "e", "d", y "a", por lo que estas cuatro variables tendrán que calcularse de manera concurrente entre ellas.

De manera gráfica, sería algo así:


Cada nodo (círculo) representa una operación, y aquellas que están bifurcadas pueden hacerse a la vez.

No obstante, como decía antes, debemos tener en cuenta el orden en que éstas se ejecutan, ya que se llegarámos a "i = g*h", siguiéramos  y todavía no se hubiera calculado "f = e*d*a", el valor de "i" sería distinto al esperado en la teoría.

Es por eso que tenemos los llamados "semáforos". Éstos, como en la vida misma, sirven para indicar cuándo un proceso tiene que esperar, para que todo vaya según lo planeamos.

En este ejemplo, en el caso planteado anteriormente, tendríamos al principio un semáforo con valor 0; luego en los nodos de "i" y "f", incrementaríamos el valor del semáforo en 1. Finalmente, en el nodo "j", haríamos que parara la ejecución hasta que el semáforo tuviera valor 2 (cuando ambas ramas se han terminado). Con los nodos "g" y "h" pasaría lo mismo.

También (como nos pasará en nuestro ejemplo) es posible que no haga falta semáforos.

Bien, ahora vamos con las peticiones:

Peticiones HTTP

En JAVA, tenemos los maravillosos buffer, que no son otra cosa que un "punto intermedio" entre dos componentes que pueden no ir a la misma velocidad.

Hay buffers en todas partes: en el teclado del PC, en la lectora de CD/DVD (algunos recordamos aquello de "buffering" cuando grabábamos un cd), en las descargas de vídeo (youtube, por ejemplo), y muchos otros sitios.

El buffer nació como solución a un problema, y es que cuando dos medios diferentes comparten información es difícil sincronizarlos.

Imaginaos que, de entre los 80 proceso que (fácilmente) tiene un ordenador, justo cuando tecleamos va la CPU y está ocupada con un proceso... constantemente perderíamos las pulsaciones. Por ello, se almacenan en un buffer, y son leídas de ahí por nuestro PC "cuando se puede" y se hace con ellas lo que se tenga que hacer.

Si queréis probar un efecto del buffer, probad a abrir un terminal (cmd, en Windows), y haced un "dir" en un directorio con muchos archivos. Mientras liste el "dir", escribid algo en el teclado...

Cuando acabe el dir, saldrá escrito aquello que hayáis escrito. Si no hubiera buffer, estas pulsaciones se hubieran perdido.

Pues bien, para hacer peticiones HTTP, creamos un buffer, para, "cuando se pueda" recoger la información.

Entonces, el proceso es el siguiente (simplificando):

 - Creamos el buffer
 - Le pasamos un objeto que no permitirá leer de ahí
 - Le damos una URL a la que hacer la petición
 - Vamos leyendo del buffer y almacenando en una variable
 - Cuando termine, devolvemos la variable

Bien, ahora vamos con un poco de práctica:

Para crear un hilo en java, debemos crear una clase que extienda la clase "Thread". Al extenderla, tendrá que implementar el método "public void run()", que es el método que "saltará" cuando llamemos al hilo.

Para llamar a un hilo, debemos hacer así:

MiHilo mh = new MiHilo(); //MiHilo es una clase que extiende a Thread
mh.start();
//seguimos con la ejecución normal, mientras mh va con su propia ejecución.

Debemos tener en cuenta que si hay datos compartidos en la teoría, ésto tiene que llevarse a la práctica.

El método que uso yo para esto es crear una clase "contenedor", que no tendrá más que todas las variables compartidas, declaradas como públicas. Luego, a las clases que extienden Thread les declaro un constructor en el que reciben un objeto de este tipo "contenedor", y sobre sus variables operamos.

Entonces, el proceso para dos hilos sería así:

Contenedor c = new Contenedor();
MiHilo hilo1 = new MiHilo(c);
MiHilo hilo2 = new MiHilo(c);
//ambos tienen la misma instancia de "Contenedor", y como JAVA pasa los parámetros por referencia (dirección de memoria, puntero), al modificar algo de "c" quedará cambiado en ambas variables (hilo1 e hilo2).

Por otra parte, para crear peticiones HTML, podemos fácilmente copiar éste método:

private String getHTML(String u) throws IOException{
URL url = new URL(u);
URLConnection con = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer sb = new StringBuffer("");
String aux;
while((aux=in.readLine()) != null) 
sb.append(aux);

return sb.toString();
}

En el que recibimos como parámetro la URL a la que queremos lanzar la petición, y recibimos como resultado el código HTML de ejecutar dicha petición, o una excepción si algo ha salido mal.

Me gustaría exponer el código que creé, pero he descubierto que hay un fallo con un Iterator (en el método que comprueba las peticiones fallidas), ya que la lista que itera está en continuo cambio (y lanza excepciones, entonces).

También me gustaría mejorar ese aspecto, pero no tengo tiempo para nada últimamente...

Si lo arreglo editaré la entrada o haré un anexo.

Entonces, la próxima entrada será sobre el tema JavaScript que tanto me fastidió en su día, y que hace un par de noches, estando tumbado en la cama, logré resolver: 

El solapamiento de eventos.

Y bueno, con esta aventurilla he cubierto (más o menos) el tema de "hacking" que tenía pensado publicar.

Me queda pendiente de explicaros algunas cosas interesantes de VB.net que pueden usarse con fructífero resultado, como el tratamiento de procesos combinado con las peticiones FTP... con un poco de investigación podemos conseguir algunas cosas...

En fin...

¡Hasta la próxima!

Interludio

Buenas!

Tenía la parte III escrita, y estaba maquetando cuando he apretado "ctrl-z" en el editor de elementos de Chrome y me ha desaparecido todo, y encima me ha guardado la entrada como vacía...

Pena penita... en fin, este fin de semana la haré de nuevo (y con más tiempo, la verdad... que la que tenía redactada era como "express"...)

Aprovecho para contaros que ayer conseguí una nueva pieza para mi PC. En concreto es la tarjeta de sonido Hercules GameSurronund Muse XL Poket LT3. Si bien no es algo "profesional", si me sirve para disfrutar como nunca de mi home cinema Trust SoundForce Presto 5.1 (que ya tiene sus casi 3 años).

Con esto queda completado mi PC, a la espera de una próxima renovación (toca gráfica, HDD o RAM)...

Como dato curioso os dejo las specs de mi PC:
  • Caja: Marca Acer (antiguamente tenía una OKI de diseño bastante guay - con silueta de deportivo)
  • PSU: Tacens Radix IV-600
  • MotherBoard: Asus P5KPL - AM EPU
  • Chipset: Intel Core2Quad Q8400 (@2.66GHz, 4M cache)
  • HDD:
    • Samsung (P)ATA 233GB
    • Seagate (S)ATA 466GB
    • Maxtor (S)ATA 190GB
  • Gráfica: nVidia GeForce 8600 GT Super+ 1GB
  • Output:
    • Teclado: Razer BlackWidow Ultimate
    • Pantalla:
      • Acer X203W
      • OKI (??)
    • Sonido:
      • Tarjeta de sonido: Hercules GameSurronund Muse XL Poket LT3
      • Speakers: Trust SoundForce Presto 5.1
    • LAN:
      • ONO @30mbps (~3.8MB/S)
Pasad buen fin de semana y...

¡Hasta la próxima!