Asignación #1

Tipos Abstractos de Datos

Para nuestra primera asignación formal tendrás que implementar un tipo abstracto de datos para números complejos, y para hacerlo será indispensable utilizar como “template” el caso del tipo de datos Fraction.

El ADT Complex debe encapsular el concepto matemático de número complejo: aquella entidad que describimos como a + i b, donde ‘a’ y ‘b’ son números  reales e ‘i’ es la unidad imaginaria. ‘a’ tiene el nombre de parte real y ‘b’ de parte imaginaria. Por eso necesitaremos, para laclase que implanta el ADT,  de dos variables de instancia: “re” e “im”.

A continuación, el código para implementar. Se trata de completar los métodos esbozados.

class Complex:
     def __init__(self,real,imagine):
         self.re = real
         self.im = imagine

     def __str__(self):
         return ......

     def __add__(self,otherComplex):
         ....
         return Complex(....)
     def __minus__(self,otherComplex):
         ....
         return Complex(....)
     def __mult__(self,otherComplex):
         ....
         return Complex(....)

     def __div__(self,otherComplex):
         ....
         return Complex(....)

     def __eq__(self, other):
        ...
         return      ... == ...

Ejemplo de uso:

x = Complex(1,2)
y = Complex(2,3)
print(x+y)
print(x == y)
print(x+y+y)

Completa el código y guárdalo en un archivo privado en tu espacio github. Escribe una entrada en tu blog e indica el trabajo hecho. Incluye un enlace al código desarrollado.

Para las operaciones de multiplicación y división, consulta un manual de matemática.

Entrega: miércoles 7 de septiembre
Tags: inf201, tarea1, ADT, Complex

Programming Languages

Compiling to Machine Code
Some languages require programs to be transformed directly into machine code the instructions that a CPU understands directly. Assembly Language, C, C++, C#, Objective C are faster than interpreted languages because the instruction are read directly from the CPU.
Interpreted Languages
Interpreted such as Python, Php and JavaScript.
An Interpreted language is processed at runtime. Every line is read, analyzed, and executed. Having to reprocess a line every time in a loop is what makes interpreted languages so slow.
C++
C++ is very old but still a very good language and is super-fast and is used for gaming because of the speed.
C#
C# syntax is very similar to Java, and is used by Microsoft like most C languages excluding Objective C they have a very similar syntax and run much faster. One of the main advantage of this language is that use .Net framework from Microsoft that is a very rich utility.
I do prefer C languages because they have a lot of libraries are identical one to another and for me is like the main programming of today with C you will find other languages very similar like Java or Php.
Java Vs Python
Python programs are generally expected to run slower than Java programs, but they also take much less time to develop. Python programs are typically 3-5 times shorter than equivalent Java programs.

In conclusion there isn’t a better programing language they are all created for a purpose some’s for web, devices, security etc.

Bank averageTask

Execution: Abajo podran ver los resultados durante la ejecución de 8 horas cual fue la mejor y peor de las simulaciones.

one two

Code: http://pastebin.com/embed_iframe.php?i=GVENSD38

Our flowChart: No es lo mismo a los métodos del código debido a que fue el primero creado para la tarea que fue presentada al profesor.


Sort Execution Time

La ejecución de los distintos algoritmos de ordenación an tenido un gran han sido muy distintos en términos de consumo de tiempo. Como podemos ver en la imagen el algoritmo más eficiente pero con el problema de la recursión limitada es el quickSort terminando una lista de 100.000 elementos en un segundo. El algoritmo menos eficiente durante las ejecuciones fue el bubbleSort debido a su forma de comparación de elementos.

| tiempo 100.000 |

importimesort

las otras ejecuciones no terminaron de tan largo que es el proceso.

ahora les dejo un ejemplo de los algoritmos de búsqueda y sus tiempos de ejecución y en este caso buscando el número 100 en una lista random de 100.000 tomo mas tiempo el binarySearch que el sequentialSearch que era bastante obvio ya que el sequential ejecuta recorriendo la lista entera en caso de que no sea encontrado y se detiene al encontrarlo.

four

Class Oct 29, 2014

resumenClass                                                                                Wed Oct 29, 2014

during this class the professor was discussing two different types of searching algorithms the first was the sequential search and the other was binary search the main reason of showing us different types of algorithm is the speed of execution and comparison of each one.

 

sequentialSearch

one

how it works?

this is the easiest search algorithm basically as you can see the code above it initialize to variables and start a while loop during the loop increase the variable pos in case the item we are looking isn’t the one on that index and continue incrementing until he can found it or return False if its not available.

five

binarySearch

 two

how it works? NEED TO BE ORDERED USE alist.sort() method

This algorithm start declaring the major variables for his execution called firs, last and found. start a while loop compare first with last and check if found is not true to execute. during the loop execution declare a variable midpoint = the sum of first and last and divides the result as a integer division by 2.

conditions

basically what this condition does is if alist[midPoint] value is equal to what we are looking for then return true and finish the execution. If not we if the item is lower than de value of alist[midPoint] and if is true decrement one to last start on the other side of the list else increment one to first.

Continue the loop until it can find the searched one or of is not on the list return false.

five

executionTime

 three 

this is a simple exercise made during the class that show us the time execution that took multiplying the largest number in a loop.

 

Resumen #2

Kevin Flores Alvarez
201-30-5386
INF – 201
Resumen

Turtle program

Es un programa basado en una metafora bastante simple en donde se le da una serie de instrucciones como izquierda, adelante, derecha, ect. Con este pensamiento, e intruscciones el turtle program puede hacer un dibujo a base de las direcciones dadas por el usuario.

import turtle               # Nos permite utilizar la libreria turtle de python

wn = turtle.Screen()        # crea una ventana grafica

alex = turtle.Turtle()      # crea un turtle llamado alex

alex.forward(150)           # le dice a alex que se mueva hacia adelante unas 150 unidades

alex.left(90)               # gira 90 grados

alex.forward(75)            # complete la segunda pared del triangulo

Un ejemplo de lo que hace un turtle.

Recursión:

Se discutió la diferencia entre un método recursivo y un método iterativo. Se tomo como ejemplo la secuencia de fibonnaci:

Método Recursivo:
def recursiveFib(num):

if num == 0:

return 0

elif num == 1:

return 1

else:

return recursiveFib(num – 1) + recursiveFib(num – 2)

print recursiveFib(4)

Metodo Iterativo:

def fibonaciNonrecursive(ammountTwo):

a = 0

b = 1

result = 1

while(1 < ammountTwo):

result = a + b

a = b

b = result

ammountTwo -= 1

print(b)

Al evaluar los dos métodos comprendimos que hacen lo mismo, pero cuando lo evaluamos desde el trazado, vimos la diferencia en donde el iterativo es más complejo. La versión recursiva se llama a sí mismo hasta llegar a una condición que produce un resultado. La versión iterativa tiene un loop en donde se ejecuta el procedimiento matemático hasta que se cumpla una condición específica.

Tower of Hanoi

La torre de hanoi fue inspirada por un ejercicio dado a los monjes de un templo hindu. El ejercicio consta en mover 63 discos de un sitio a otro con dos condicionales.
1. Solo pueden mover un disco a la vez
2. No pueden haber discos más grandes arriba de los más pequeños.

El número de veces que ellos tenían que mover los discos para completar el ejercicio es de 264−1=18,446,744,073,709,551,615. Si mueven un solo disco por segundo eso sería equivalente a 584,942,417,355 años

Aqui tienen un outline de como mover una torre de primera posicion a la final usando la torre intermedia

  1. Mover una torre de altura -1 a la torre intermedia, usando la torre final.
  2. Mover el resto de los discos a la torre final
  3. Mover la torre de altura -1 de la torre intermedia a la torre final usando la torre original

def moveTower(height,fromPole, toPole, withPole):

if height >= 1:

moveTower(height-1,fromPole,withPole,toPole)

moveDisk(fromPole,toPole)

moveTower(height-1,withPole,toPole,fromPole)

def moveDisk(fp,tp):

print(“moving disk from”,fp,”to”,tp)

moveTower(3,”A”,”B”,”C”)

Usando este código podemos resolver la torre de hanoi, pero tomaria mucho tiempo en resolver debido a las condicionales. Las torres utilizan lo que se le conoce como stack en python para poner un disco sobre otro; también utilizando FIFO (first in First out) para poder mover los discos de una torre a otra.

Inheritance: Logic Gates and Circuits

La herencia entre clases es la habilidad en una clase de estar relacionada con otra clase así como si fueran familias. Del mismo modo, las clases hijas de Python pueden heredar datos de características y el comportamiento de una clase padre. Estas clases se refieren a menudo como subclases y superclases.

La siguiente figura muestra las colecciones de Python incorporadas y sus relaciones mutuas. Llamamos a una estructura de relación como esta jerarquía de una herencia. Por ejemplo, la lista es un hijo de la colección secuencial. En este caso, llamamos a la lista del niño y la secuencia de los padres (o lista de subclase y superclase secuencia). Esto se refiere a menudo como una “IS-A Relationship” (La lista IS-A colección secuencial). Esto implica que las listas heredan características importantes de las secuencias, es decir, el orden de los datos subyacentes y operaciones tales como concatenación, la repetición, y la indexación.

Una jerarquía de herencia para Python Coletions

../_images/inheritance1.png

Listas, tuplas, y las cadenas son todos los tipos de colecciones secuenciales. Todos ellos heredan organización y operaciones de datos común. Sin embargo, cada uno de ellos se basa distinta de si los datos es homogénea y si la colección es inmutable. Todos los niños se benefician de sus padres, pero se distinguen por la adición de características adicionales.

Mediante la organización de clases de código de esta manera jerárquica, los lenguajes de programación orientados a objetos permiten previamente escritos para ser ampliado para satisfacer las necesidades de una nueva situación. Además, mediante la organización de datos de esta manera jerárquica, podemos entender mejor las relaciones que existen. Podemos ser más eficientes en la construcción de nuestras representaciones abstractas.

Para explorar esta idea, vamos a construir una simulación, una aplicación para simular circuitos digitales. El bloque de construcción básico para esta simulación será la puerta lógica. Estos interruptores electrónicos representan relaciones álgebra de Boole entre su entrada y su salida. En general, las puertas tienen una sola línea de salida. El valor de la salida es dependiente de los valores dados en las líneas de entrada.

AND gates tienen dos líneas de entrada, cada uno de los cuales puede ser 0 o 1 (en representación de falso o verdadero, repectively). Si las dos líneas de entrada tiene el valor 1, la salida resultante es 1 Sin embargo, si uno o ambos de las líneas de entrada es 0, el resultado es 0 OR gates también tener dos líneas de entrada y producir un 1 si uno o ambos de los valores de entrada es un 1. En el caso en el que ambas líneas de entrada son 0, el resultado es 0.

NOT gates se diferencian de las otras dos puertas en el que sólo tienen una sola línea de entrada. El valor de salida es simplemente el opuesto del valor de entrada. Si es 0 aparece en la entrada, 1 se produce en la salida. Del mismo modo, produce 1 0. La próximo imagen muestra cómo cada una de estas puertas está representado típicamente. Cada puerta tiene también una tabla de verdad de los valores que muestran el mapeo de input-to-output que es realizado por la puerta.

../_images/truthtable.png

Mediante la combinación de estas puertas en varios patrones y luego aplicar un conjunto de valores de entrada, podemos construir circuitos que tienen funciones lógicas. La figura que se ve a continuación muestra un circuito que consta de dos AND gates, un OR gate y un NOT gate. Las líneas de salida de los dos AND gates se alimentan directamente al OR gate, y la salida resultante del OR gate se da al NOT gate. Si aplicamos un conjunto de valores de entrada a las cuatro líneas de entrada (dos para cada puerta), los valores son procesados ​​y el resultado aparece en la salida del NOT gate. La figura que se ve a continuación también muestra un ejemplo con valores.

../_images/circuit1.png

Con el fin de implementar un circuito, debemos crear una representación de puertas lógicas. Las puertas lógicas se organizan fácilmente en una jerarquía de herencia de clases como se muestra en etas imagen. En la parte superior de la jerarquía, la clase LogicGate representa las características más generales de puertas lógicas: a saber, una etiqueta para la puerta y una línea de salida. El siguiente nivel de subclases rompe las puertas lógicas en dos familias, los que tienen una línea de entrada y los que tienen dos. Debajo de eso, aparecen las funciones lógicas específicas de cada uno.

../_images/gates.png

Ahora podemos empezar a aplicar las clases comenzando con la más general, LogicGate. Como se señaló anteriormente, cada puerta tiene una etiqueta para la identificación y una sola línea de salida. Además, necesitamos métodos para permitir a un usuario de una puerta para hacer la puerta de su etiqueta.

El otro comportamiento que necesita cada puerta lógica es la capacidad de conocer su valor de salida. Para ello será necesario que la puerta realice la lógica apropiada basada en la entrada de corriente. Con el fin de producir una salida, la puerta tiene que saber específicamente cuál es esa lógica. Esto significa llamar a un método para realizar el cálculo de la lógica.

class LogicGate:

    def __init__(self,n):
        self.label = n
        self.output = None

    def getLabel(self):
        return self.label

    def getOutput(self):
        self.output = self.performGateLogic()
        return self.output

En este punto, no vamos a implementar la función performGateLogic. La razón de esto es que no sabemos cómo cada puerta realizará su propia operación lógica. Esos detalles se incluirán por cada puerta individual que se añade a la jerarquía. Esta es una idea muy poderosa en la programación orientada a objetos. Estamos escribiendo un método que utilizará el código que aún no existe. El parámetro auto es una referencia al objeto de puerta real de invocar el método. Cualquier nueva puerta lógica que se agrega a la jerarquía sólo tendrá que implementar la función performGateLogic y será utilizado en el momento apropiado. Una vez hecho esto, la puerta puede proporcionar su valor de salida. Esta capacidad de extender una jerarquía que existe actualmente y proporcionar las funciones específicas que la jerarquía necesita usar la nueva clase es extremadamente importante para la reutilización de código existente.

Hemos clasificado las puertas lógicas en función del número de líneas de entrada. La puerta Y tiene dos líneas de entrada. OR gate también cuenta con dos líneas de entrada. NOT gates tienen una línea de entrada. La clase BinaryGate será una subclase de LogicGate y añadirá dos líneas de entrada. La clase UnaryGate también subclase LogicGate pero tendrá una única línea de entrada. En el diseño de circuitos de ordenador, estas líneas son a veces llamados “bolos” por lo que vamos a utilizar esa terminología en nuestra aplicación.

Listing 9

class BinaryGate(LogicGate):

    def __init__(self,n):
        LogicGate.__init__(self,n)

        self.pinA = None
        self.pinB = None

    def getPinA(self):
        return int(input("Enter Pin A input for gate "+ self.getLabel()+"-->"))

    def getPinB(self):
        return int(input("Enter Pin B input for gate "+ self.getLabel()+"-->"))

Listing 10

class UnaryGate(LogicGate):

    def __init__(self,n):
        LogicGate.__init__(self,n)

        self.pin = None

    def getPin(self):
        return int(input("Enter Pin input for gate "+ self.getLabel()+"-->"))

Listado 9 y Listado 10 implementan estas dos clases. Los constructores de estas dos clases comienzan con una llamada explícita al constructor de la clase padre utilizando el método __init__ de los padres. Al crear una instancia de la clase BinaryGate, primero queremos inicializar cualquier elementos de datos que se heredan de LogicGate. En este caso, eso significa que la etiqueta de la puerta. El constructor pasa luego añadir las dos líneas de entrada (Pina y pinB). Este es un patrón muy común que siempre se debe utilizar en la construcción de jerarquías de clases. Constructores de clase del niño tienen que llamar a los constructores de la clase padre y luego pasar a sus propios datos distintivos.

Python también tiene una función llamada súper que se puede utilizar en lugar de nombrar explícitamente la clase padre. Este es un mecanismo más general, y es ampliamente utilizado, especialmente cuando una clase tiene más de un padre. Pero, esto no es algo que vamos a discutir en esta introducción. Por ejemplo, en nuestro ejemplo anterior LogicGate .__ init __ (self, n) podría sustituirse con super (UnaryGate, auto) .__ init __ (n).

El único comportamiento que la clase BinaryGate añade es la capacidad de obtener los valores de las dos líneas de entrada. Puesto que estos valores vienen de un lugar externo, simplemente vamos a pedir al usuario a través de una declaración de entrada para su prestación. La misma aplicación se produce para la clase UnaryGate la excepción de que sólo hay una línea de entrada.

Ahora que tenemos una clase general de puertas en función del número de líneas de entrada, podemos construir puertas específicas que tienen un comportamiento único. Por ejemplo, la clase AndGate será una subclase de BinaryGate desde AND gates tener dos líneas de entrada. Al igual que antes, la primera línea del constructor exhorta al constructor de la clase padre (BinaryGate), que a su vez llama a su constructor de la clase padre (LogicGate). Tenga en cuenta que la clase AndGate no proporciona ningún dato nuevo, ya que hereda dos líneas de entrada, una línea de salida, y una etiqueta.

class AndGate(BinaryGate):

    def __init__(self,n):
        BinaryGate.__init__(self,n)

    def performGateLogic(self):

        a = self.getPinA()
        b = self.getPinB()
        if a==1 and b==1:
            return 1
        else:
            return 0

La única cosa AndGate necesita añadir es el comportamiento específico que realiza la operación booleana que se describió antes. Este es el lugar donde podemos proporcionar el método performGateLogic. Por una puerta, este método primero debe obtener los dos valores de entrada y sólo devuelve 1 si los dos valores de entrada son 1.

Podemos mostrar la clase AndGate en acción mediante la creación de una instancia y pidiéndole que calcular su salida. La siguiente sesión muestra un objeto AndGate, g1, que tiene una etiqueta interna “G1″. Cuando invocamos el método getOutput, el objeto primero debe llamar a su método performGateLogic que a su vez consulta las dos líneas de entrada. Una vez que se proporcionan los valores, se muestra la salida correcta.

>>> g1 = AndGate("G1")
>>> g1.getOutput()
Enter Pin A input for gate G1-->1
Enter Pin B input for gate G1-->0
0

La misma evolución se puede hacer para OR gates y NOT gates. La clase OrGate también será una subclase de la clase y BinaryGate NotGate se extenderá la clase UnaryGate. Ambas clases tendrá que proporcionar sus propias funciones performGateLogic, ya que este es su comportamiento específico.

Podemos utilizar una sola puerta construyendo primero una instancia de una de las clases de puerta y luego pedir a la puerta de su producción (que a su vez necesitan insumos deberá presentarse). Por ejemplo:

>>> g2 = OrGate("G2")
>>> g2.getOutput()
Enter Pin A input for gate G2-->1
Enter Pin B input for gate G2-->1
1
>>> g2.getOutput()
Enter Pin A input for gate G2-->0
Enter Pin B input for gate G2-->0
0
>>> g3 = NotGate("G3")
>>> g3.getOutput()
Enter Pin input for gate G3-->0
1

Ahora que tenemos las puertas básicas de trabajo, podemos dirigir nuestra atención a la construcción de circuitos. Con el fin de crear un circuito, que necesitamos para conectar puertas juntos, la salida de uno que fluye en la entrada de otro. Para ello, vamos a implementar una nueva clase llamada Connector.

La clase de conector no residir en la jerarquía de la puerta. Será, sin embargo, utilizar la jerarquía de la puerta en que cada conector tendrá dos puertas, una en cada extremo. Esta relación es muy importante en la programación orientada a objetos. Se llama el HAS-A Relationship. Recordemos antes de que se utilizó la frase “IS-A Relationship” decir que una clase hija se relaciona con una clase padre, por ejemplo UnaryGate IS-A LogicGate.

../_images/connector.png

Ahora, con la clase Connector, decimos que un conector HAS-A LogicGate lo que significa que los conectores se tienen instancias de la clase LogicGate dentro de ellos, pero no son parte de la jerarquía. En el diseño de las clases, es muy importante distinguir entre los que tienen la relación es-un (que requiere la herencia) y los que tienen relaciones HAS-A (sin herencia).

Listado 12 muestra la clase Connector. Los dos instancias de puerta dentro de cada objeto de conector se hará referencia como el fromgate y la togate, reconociendo que los valores de los datos se “flujo” de la salida de una compuerta en una línea de entrada de la siguiente. La llamada a setNextPin es muy importante para hacer las conexiones. Tenemos que añadir este método para nuestras clases de puerta para que cada togate puede elegir la línea de entrada adecuada para la conexión.

Listing 12

class Connector:

    def __init__(self, fgate, tgate):
        self.fromgate = fgate
        self.togate = tgate

        tgate.setNextPin(self)

    def getFrom(self):
        return self.fromgate

    def getTo(self):
        return self.togate

En la clase BinaryGate, para puertas con dos posibles líneas de entrada, el conector debe estar conectado a una sola línea. Si ambos están disponibles, elegiremos pinA por defecto. Si pinA ya está conectado, después elegiremos pinB. No es posible conectarse a una puerta sin líneas de entrada disponibles.

def setNextPin(self,source):
    if self.pinA == None:
        self.pinA = source
    else:
        if self.pinB == None:
            self.pinB = source
        else:
           raise RuntimeError("Error: NO EMPTY PINS")

Ahora es posible obtener la entrada a partir de dos lugares: externamente, como antes, y desde la salida de una puerta que está conectado a la línea de entrada. Esto requiere un cambio en los métodos getPinA y getPinB. Si la línea de entrada no está conectado a nada (None), preguntar al usuario externo como antes. Sin embargo, si hay una conexión, se accede a la conexión y el valor de salida de fromgate se recupera. Esto a su vez hace que la puerta para procesar su lógica. Esto continúa hasta que todas las entradas está disponible y el valor de salida final se convierte en la entrada necesaria para la puerta en cuestión. En cierto sentido, el circuito funciona hacia atrás para encontrar la información necesaria para finalmente producir una salida.

def getPinA(self):
    if self.pinA == None:
        return input("Enter Pin A input for gate " + self.getName()+"-->")
    else:
        return self.pinA.getFrom().getOutput()

El siguiente fragmento construye el circuito mostrado anteriormente en la sección:

>>> g1 = AndGate("G1")
>>> g2 = AndGate("G2")
>>> g3 = OrGate("G3")
>>> g4 = NotGate("G4")
>>> c1 = Connector(g1,g3)
>>> c2 = Connector(g2,g3)
>>> c3 = Connector(g3,g4)

Las salidas de los dos AND gates (G1 y G2) están conectados al OR gate (g3) y que está conectado a la salida del NOT gate (g4). La salida de la NOT gate es la salida de todo el circuito. Por ejemplo:

>>> g4.getOutput()
Pin A input for gate G1-->0
Pin B input for gate G1-->1
Pin A input for gate G2-->1
Pin B input for gate G2-->1
0

Esto también los puedes encontrar en el libro Problem Solving with Algorithms and Data Structures

Python – Compuertas Logicas(Presentation & Source Code)

Sample Code

class LogicGate:

def __init__(self,n):
self.name = n
self.output = None

def getName(self):
return self.name

def getOutput(self):
self.output = self.performGateLogic()
return self.output

class BinaryGate(LogicGate):

def __init__(self,n):
LogicGate.__init__(self,n)

self.pinA = None
self.pinB = None

def getPinA(self):
if self.pinA == None:
return int(input(“Enter Pin A input for gate “+self.getName()+”–>”))
else:
return self.pinA.getFrom().getOutput()

def getPinB(self):
if self.pinB == None:
return int(input(“Enter Pin B input for gate “+self.getName()+”–>”))
else:
return self.pinB.getFrom().getOutput()

def setNextPin(self,source):
if self.pinA == None:
self.pinA = source
else:
if self.pinB == None:
self.pinB = source
else:
print(“Cannot Connect: NO EMPTY PINS on this gate”)

class AndGate(BinaryGate):

def __init__(self,n):
BinaryGate.__init__(self,n)

def performGateLogic(self):

a = self.getPinA()
b = self.getPinB()
if a==1 and b==1:
return 1
else:
return 0

class OrGate(BinaryGate):

def __init__(self,n):
BinaryGate.__init__(self,n)

def performGateLogic(self):

a = self.getPinA()
b = self.getPinB()
if a ==1 or b==1:
return 1
else:
return 0

class UnaryGate(LogicGate):

def __init__(self,n):
LogicGate.__init__(self,n)

self.pin = None

def getPin(self):
if self.pin == None:
return int(input(“Enter Pin input for gate “+self.getName()+”–>”))
else:
return self.pin.getFrom().getOutput()

def setNextPin(self,source):
if self.pin == None:
self.pin = source
else:
print(“Cannot Connect: NO EMPTY PINS on this gate”)

class NotGate(UnaryGate):

def __init__(self,n):
UnaryGate.__init__(self,n)

def performGateLogic(self):
if self.getPin():
return 0
else:
return 1

class Connector:

def __init__(self, fgate, tgate):
self.fromgate = fgate
self.togate = tgate

tgate.setNextPin(self)

def getFrom(self):
return self.fromgate

def getTo(self):
return self.togate

def main():
g1 = AndGate(“G1″)
g2 = AndGate(“G2″)
g3 = OrGate(“G3″)
g4 = NotGate(“G4″)
c1 = Connector(g1,g3)
c2 = Connector(g2,g3)
c3 = Connector(g3,g4)
print(g4.getOutput())

main()

Presentation Class

Source Code – Not Documented

http://pastebin.com/embed_iframe.php?i=6chnNBqq

Source Code – Documented

http://pastebin.com/embed_iframe.php?i=TrQMmT3y

Estructura de Datos / USC