Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

jueves, 11 de abril de 2019

Calculando el Conjunto de Wirt (entrada antigua)

(esta entrada estaba originalmente en Electrónica a Martillazos, como tener un hosting gratuito se volvió una pesadilla, he decidido copiar las viejas entradas aquí y mandar la web original al olvido. Como son entradas muy viejas, es posible que algunos links estén más muertos que Altavista, Enjoy!). 

Una implementación mejor está aquí.

En la página de PuntoPeek encontré el siguiente problema propuesto: "Calcular los n primeros números del conjunto de Wirth".

El conjunto de Wirth se define de la siguiente manera:
"El conjunto de Wirth es un subconjunto de los enteros positivos que cumple con la siguiente regla: el 1 pertenece al conjunto y si un numero k pertenece al conjunto entonces los números 2*k+1 y 3*k+1 pertenecen al conjunto."
La solución de PuntoPeek es mucho mejor. No calcula números extra.
Por mi parte, no hubiera seguido insistiendo con el problema del Conjunto de Wirth si no hubiera tenido la sensación que la solución es mucho, pero mucho más simple.

Para empezar me basé en la solución propuesta de PuntoPeek. Luego de analizarla a simple vista, noté que todo se reduce a:
1. En un array de tamaño fijo n ingreso el 1 como primer elemento,
2. Recorro todos los números naturales y le pregunto a cada uno: ¿eres el resultado de tomar un número k del array y realizar las operaciones: 3k+1 ó 2k+1? si es así, te añado al array.
3. Me detengo hasta completar todos los elementos del array.
Lo curioso es que el postulado del conjunto de Wirth hace pensar en una operación "y" (and lógica): "Si un número k es elemento del conjunto, también lo son los números 3k+1 y 2k+1", cuando en realidad es un or lógico: cada número k del conjunto genera 3k + 1 y 2k + 1. Entonces, para que otro número i sea del conjunto debe cumplir cualquiera de estas dos condiciones: i = 3k + 1 ó i = 2k + 1. O mejor dicho: (i-1)/3 ó (i-1)/2 debe darnos un número k que ya está en nuestro array..
Con el método de PuntoPeek se buscan los primeros números n preguntando si cumplen cualquiera de las dos condiciones. La variable k es conocida, pues ya está almacenada en el array.
En Python, el algoritmo es:


Uso datos de tipo float (coma flotante) para descartar los números que den resultados decimales (la variable i es en realidad un entero con representación flotante). Así evito falsos positivos o falsos rechazados por los errores que se introducen al redondear la división entre enteros.
El resultado es:



Lo interesante de este algoritmo es que sirve para generar cualquier serie de números que cumplan una condición. Basta cambiar los primeros elementos del array y la condición, pues lo que en realidad hace es extraer del conjunto de los números naturales todos aquellos números que cumplen una condición.
La serie Fibonacci se genera de la siguiente forma (como no implica divisiones, no necesito números de coma flotante):



Para las potencias de 2:



Para los factoriales (números que son el factorial de otro):




def Wirt(n):
    result = [1.0]

    i=1.0
    while len(result)<=n:
        i+=1.0
        if (i not in result and ((i-1)/2 in result or (i-1)/3 in result)):
            result.append(i)

    return [int(x) for x in result]

def Fib(n):
    result = [0, 1]

    i=0
    while len(result)<=n:       
        i+=1
        if i== result[-1] + result[-2]:
            result.append(i)       

    return result

def Pot2(n):
    result = []

    i=0
    p=0
    while len(result)<=n:       
        i+=1
        if i== 2**p:
            result.append(i)
            p+=1

    return result

def Fact(n):

    def fact(p):
        if p==1:
            return p
        else:
            return p*fact(p-1)

    result = []

    i=0
    p=1
    while len(result)<=n:       
        i+=1
        if i== fact(p):
            result.append(i)
            p+=1

    return result

print Wirt(50)
print Fib(10)
print Pot2(10)
print Fact(5)

 

Lo malo de este algoritmo: para el caso del factorial y las potencias de dos es lentísimo. Tarda horas (literalmente) en calcular potencias de 2 mayores a 2^20, y lo mismo sucede para factoriales mayores al factorial de 10. Ir preguntando a cada número si cumple una condición es muy ineficiente para series de números cuyos valores crecen de forma geométrica o exponencial.

Pero ha sido una buena práctica de aprendizaje :)

lunes, 1 de abril de 2019

Probando los SCRs

(esta entrada estaba originalmente en Electrónica a Martillazos, como tener un hosting gratuito se volvió una pesadilla, he decidido copiar las viejas entradas aquí y mandar la web original al olvido).

Sucedió que encontré varios SCRs ("Rectificadores Controlados de Silicio" como son los triacs y tiristores) los que ya daban por dañados. Después de tenerlos guardados algunos meses decidí probar si funcionaban o no. Al no tener plena confianza en el método de prueba con el multímetro que nos enseñó el profesor decidí buscar en internet otro método más confiable.
No lo encontré.
Bueno, había webs acerca de usar el multímetro para comprobar si los SCRs están operativos o no, pero cuando al aplicar estos métodos en los míos me salía que todos estaban dañados. Fue cuando perdí la paciencia y decidí que la mejor manera de probarlos de una vez por todas era armar el circuito básico con el que se los hace funcionar, y hacerlos funcionar.

El circuito es éste, y es de lo más sencillo:



Que no es más que el circuito básico de disparo de un SCR. En el caso de los tiristores, éstos poseen 3 terminales: ánodo ("A", la terminal positiva), cátodo ("K" o la terminal negativa) y la compuerta (Gate). 
Los SCRs funcionan como switches que se cierran si reciben un pulso de corriente a través de la compuerta Gate y seguirán permitiendo el paso de la corriente por las otras dos terminales aunque ya no haya corriente de compuerta (en la jerga de electrónica se dice que se quedan "clavados" o "enganchados", y a la corriente de compuerta se le llama "corriente de disparo"). Para saber la corriente mínima que se necesita para "disparar" el SCR, y la máxima que puede soportar, es necesario leer el datasheet. En mi caso usé los tiristores de la serie BT151 y triacs de la serie BT136.
Los Triacs también poseen 3 terminales: uno de ellos es la compuerta y los otros dos se llaman Terminal 1 y Terminal 2, siendo intercambiables entre sí pues un triac puede conducir la corriente en ambos sentidos (es muy útil si se emplea voltaje alterno), al contrario de un tiristor que sólo conduce en un sentido al igual que un diodo en polarización directa.
Con respecto al cátodo, un tiristor sólo puede dispararse si recibe una corriente de disparo positiva. Un triac puede dispararse con corriente tanto negativa como positiva (o corriente en ambos sentidos, considerando que un triac no tiene un cátodo propiamente dicho).
Para probar los triacs y tiristores usé el mismo circuito, lo único se que hace es intercambiar los SCRs (la ventaja de las series BT151 y BT136 es que tienen la compuerta en el mismo lugar).
El circuito que armé es el siguiente:


Aquí quiero recalcar que es mejor usar un pequeño motor DC a un led, la batería es de 9 voltios y eso es demasiado para un led (que generalmente soportan menos de 5 voltios) por lo que quemé un par de ellos al probar este circuito, incluso al ponerle la resistencia en serie con el led, ésta se calentaba bastante. Pero para fines de demostración está bien (y si no se les tiene mucho cariño a los leds, por supuesto). El valor de la resistencia depende de la corriente que entrega la fuente, para una corriente mínima 10 mA y considerando un led de 3 voltios (los más comunes) y una fuente de 9 voltios:

0.01=(9-3)/R
R=700 ohmios

El cual se considera un valor máximo para la resistencia. En la práctica resulta ser demasiado alto si se usa una pila o batería gastada como la que yo usé. A veces con 200 ohmios el led apenas se enciende. El valor de la resistencia se irá bajando hasta un valor adecuado, donde el led se encienda sin quemarse.
En el caso de un motor no es necesaria la resistencia. La fuente tampoco debe tener un valor muy pequeño ya que existe un voltaje mínimo que debe haber entre las otras dos terminales del SCR para que éste se dispare, en este punto también recomiendo leer el datasheet.
Para no hacer confusión al led (o el motor) se le llamara "carga" que es el nombre genérico de las cosas que se conectan a un circuito y que se desean hacer funcionar.
El cable cocodrilo rojo va conectado a la compuerta (cuidando que no toque las otras patas del SCR) y funciona como el switch que va del polo positivo de la fuente a la compuerta. Mientras esté desconectado la carga debe estar apagada o desactivada. Si se enciende significa que el SCR está cruzado y debe descartarse.
Luego lo que se hace es tocar por un instante (apenas un pequeño toque) el polo positivo de la fuente (en este caso la batería) con el cable cocodrilo rojo:



En este caso la carga debe activarse y quedarse activada aunque el cable cocodrilo rojo ya no esté tocando la fuente. Si esto sucede así el SCR se ha quedado "clavado" y significa que está en buen estado. Si la carga se apaga al quitar el cable cocodrilo rojo el SCR no "engancha" y también debe descartarse.
En el caso de un tiristor, si se intercambian el ánodo con el cátodo y se hace la prueba de disparo también se puede comprobar la polaridad