<jupyter_start><jupyter_text>IWI131 Programación de Computadores <NAME>http://progra.usm.cl/ https://www.github.com/usantamaria/iwi131  ¿Qué contenido aprenderemos?* Conjuntos y sus operaciones  ¿Porqué aprenderemos ese contenido?* Conjuntos y sus operacionesPorque muchos problemas pueden resolverse de manera extremadamente sencilla utilizando conjuntos. ***¡Ahorre tiempo, aprenda conjuntos!***  Motivación: letras en comúnEscriba una función letras_en_comun(p,r) que retorne la cantidad de letras en común que tienen las palabras p y r.Por ejemplo:- letras_en_comun('murcielago', 'gominola')   debería regresar 6- letras_en_comun('protozoo', 'agasajada')   debería regresar 0  Motivación: letras en comúnSolución sólo con strings. Poco intuitivo, ¿verdad?<jupyter_code># Utilizando strings
def letras_en_comun(p, r):
    n = 0
    letras_a_revisar = p + r
    letras_vistas = ""
    for c in letras_a_revisar:
        if (c in p) and (c in r) and not (c in letras_vistas):
            n += 1
        letras_vistas += c 
    return n

## Verificación
print(letras_en_comun('murcielagoo', 'gominola')) # 6
print(letras_en_comun('protozoo', 'agasajada'))  # 0<jupyter_output><empty_output><jupyter_text>Conjuntos Conceptos* Se pueden definir mediante     {elemento_1, elemento_2, ..., elemento_n}o bien    set(mi_lista)* Elementos de un conjunto puede ser cualquier objeto inmutable en python.* No existen repeticiones de elementos.* ***NO*** existe indexación ni orden en un conjunto.* NO CONFUNDIR CONJUNTOS CON DICCIONARIOS:        {"uno" : 1, "dos" : 2}    {"uno", 1, "dos", 2}  Conjuntos Ejemplo<jupyter_code>colores_1 = {'rojo', 'gris', 'azul', 'gris'}
colores_2 = set(['azul', 'gris', 'rojo', 'rojo', 'rojo'])
print colores_1
print colores_2
print colores_1==colores_2
#print colores_1[0] # Esto da error

print set('abracadabra')
print set(list('abracadabra'))
print set(['a', 'b', 'c', 'd', 'r', 'c', 'd', 'r'])<jupyter_output>set(['rojo', 'azul', 'gris'])
set(['rojo', 'azul', 'gris'])
True
set(['a', 'r', 'b', 'c', 'd'])
set(['a', 'r', 'b', 'c', 'd'])
set(['a', 'c', 'b', 'r', 'd'])<jupyter_text>Importante* set(mi_lista) regresa un nuevo objeto: el conjunto de los elementos no repetidos de la lista. * set(string) regresa el conjunto de las letras no repetidas del string.* Al aplicar set se obtiene un conjunto SIN orden de elementos y SIN elementos repetidos.<jupyter_code>print set([1,2,1,2,3,4,3,2,1])
print set("abecedario")
print set(["aa","ab", "ba", "bb", "aa"])<jupyter_output>set([1, 2, 3, 4])
set(['a', 'c', 'b', 'e', 'd', 'i', 'o', 'r'])
set(['aa', 'ab', 'ba', 'bb'])<jupyter_text>ImportanteEn un conjunto no importa el orden, sino la pertenencia.Operaciones en un conjunto:1. Agregar y sacar elementos.3. Verificar pertenencia2. Recorrer un conjunto.4. Número de elementos y operaciones de conjuntos.  Conjuntos 1. Agregar y sacar elementos del conjuntoUtilizar los métodos `mi_conjunto.add(elemento)` y `mi_conjunto.remove(elemento)` 2. Verificar pertenenciaUtilizar `in`<jupyter_code>a = set() # conjunto vacio
a.add(19)
a.add(12)
a.add(8)
a.add(12)
print a # set([8, 19, 12])
a.remove(8)
print a # set([19, 12])

print 12 in a # True
print 8 in a # False<jupyter_output>set([8, 19, 12])
set([19, 12])
True
False<jupyter_text>Conjuntos 3. Operaciones básicas sobre conjuntos* Número de elementos:   `len(mi_set)`* Intersección:   `mi_set_1 & mi_set_2`* Unión:   `mi_set_1 | mi_set_2`* Diferencia:   `mi_set_1 - mi_set_2`* Subconjuntos propios: `mi_set_1  mi_set_2` * Subconjuntos: `mi_set_1 = mi_set_2`<jupyter_code>a = {1,2,3,4}
b = set(range(2,9,2))
c = set([2,4,8,16,32])
d = {2,3}
print "a=", a
print "len(a)=", len(a)
print "b=", b
print "len(b)=", len(b)
print "c=", c
print "len(c)=", len(c)
print "a&b=", a & b
print "a|b=", a | b
print "a-b=", a - b
#print "a+b=", a + b
print "a < a=", a < a
print "a <= a=", a <= a
print "d <= a=", d < a
print "a <= d=", a < d<jupyter_output>a= set([1, 2, 3, 4])
len(a)= 4
b= set([8, 2, 4, 6])
len(b)= 4
c= set([8, 16, 2, 4, 32])
len(c)= 5
a&b= set([2, 4])
a|b= set([1, 2, 3, 4, 6, 8])
a-b= set([1, 3])
a < a= False
a <= a= True
d <= a= True
a <= d= False<jupyter_text>Conjuntos 4. Utilizando ciclo forEs posible utilizar ciclo for de manera directa sobre el conjunto.(Pero no se podría utilizar un ciclo while! :)<jupyter_code># Funciona
colores = {"rojo", "verde", "rojo", "verde", "azul"}
for color in colores:
    print color, "es un bello color"
# Da error
colores = {"rojo", "verde", "rojo", "verde", "azul"}
#colores = list(colores)
j=0
while j<len(colores):
    print colores[j], "es un bello color"
    j+=1<jupyter_output>rojo es un bello color
azul es un bello color
verde es un bello color<jupyter_text>Conjuntos Ejemplos: Otras operaciones sobre conjuntos* Diferencia Simétrica de 2 conjuntos * Intersección de 3 conjuntos<jupyter_code>a = {1,2,3,4}
b = set(range(2,9,2))
c = set([2,4,8,16,32])
print a
print b
print c
# Diferencia simetrica
print (b-a) | (a-b)
print (b|a) - (a&b)
# Interseccion de 3 conjuntos
print a&b&c<jupyter_output>set([1, 2, 3, 4])
set([8, 2, 4, 6])
set([8, 16, 2, 4, 32])
set([8, 1, 3, 6])
set([8, 1, 3, 6])
set([2, 4])<jupyter_text>Ejercicio: letras en comúnEscriba una función letras_en_comun(p,r) que retorne la cantidad de letras (distintas) en común que tienen las palabras p y r.Por ejemplo:- letras_en_comun('murcielago', 'gominola')   debería regresar 6- letras_en_comun('protozoo', 'agasajada')   debería regresar 0<jupyter_code># Utilizando diccionarios
def letras_en_comun(p, r):
    # Obtener el primer conjunto de letras
    p1 = set(p)
    # Obtener el segundo conjunto de letras
    r1 = set(r)
    # Intersectar los conjuntos
    interseccion = p1 & r1
    # Contar el número de elementos comunes
    return len(interseccion)

## Verificación
print(letras_en_comun('murcielagoo', 'gominola')) # 6
print(letras_en_comun('protozoo', 'agasajada'))  # 0<jupyter_output>6
0<jupyter_text>Solución: letras en común v1Escriba una función letras_en_comun(p,r) que retorne la cantidad de letras en común que tienen las palabras p y r.<jupyter_code># Utilizando conjuntos, versión extendida
def letras_en_comun(p, r):
    # Obtener el primer conjunto de letras
    A = set(p)
    # Obtener el segundo conjunto de letras
    B = set(r)
    # Intersectar los conjuntos
    C = A & B
    # Contar el número de elementos comunes
    n = len(C)
    return n

## Verificación
print(letras_en_comun('murcielagoo', 'gominola')) # 6
print(letras_en_comun('protozoo', 'agasajada'))  # 0<jupyter_output><empty_output><jupyter_text>Solución: letras en común 2Escriba una función letras_en_comun(p,r) que retorne la cantidad de letras en común que tienen las palabras p y r.<jupyter_code># Utilizando conjuntos, versión reducida
def letras_en_comun(p, r):
    return len(set(p) & set(r))

## Verificación
print(letras_en_comun('murcielagoo', 'gominola')) # 6
print(letras_en_comun('protozoo', 'agasajada'))  # 0<jupyter_output>6
0<jupyter_text>Ejercicio: elementos en comúnSe tiene la siguiente lista de listas. ¿Cómo se puede conocer el número de elementos no repetidos?<jupyter_code>def elementos(mis_listas):
    # FIX ME
    return
        
mi_lista = [ ["uno", "dos", "tres", "cuatro", "cinco"],
             ["dos", "cuatro", "seis", "ocho", "diez"],
             ["uno", "uno", "dos", "tres", "cinco", "ocho", "once"],
             # ...
           ]

#print set(mi_lista) # da error
print elementos(mi_lista) # Deberia dar 9
# Solución
def elementos(mis_listas):
    elementos = set()
    for lista in mis_listas:
        elementos = elementos | set(lista) # += , |=
        #elementos |= set(lista) # += , |=
    return elementos
        
mi_lista = [ ["uno", "dos", "tres", "cuatro", "cinco"],
             ["dos", "cuatro", "seis", "ocho", "diez"],
             ["uno", "uno", "dos", "tres", "cinco", "ocho", "once"],
             # ...
           ]

print elementos(mi_lista) # Deberia dar 9<jupyter_output>set(['diez', 'seis', 'ocho', 'cuatro', 'cinco', 'dos', 'tres', 'once', 'uno'])<jupyter_text>Ejercicio: elementos en común v2Se tiene el siguiente diccionario. * ¿Cómo se puede obtener una tupla con las llaves no repetidos?* ¿Cómo se puede obtener una lista con los valores no repetidos?<jupyter_code>d = {"uno":1, "one":1, "un":1,
     "dos":2, "two":2, "deux":2,
     "tres":3, "three":3, "trois":3,
     # ...
    }
# Tupla de llaves no repetidas
print tuple(set(d.keys()))
# Lista de valores no repetidos
print list(set(d.values()))
# Solución
d = {"uno":1, "one":1, "un":1,
     "dos":2, "two":2, "deux":2,
     "tres":3, "three":3, "trois":3,
     # ...
    }
# Tupla de llaves no repetidas
print tuple(set(d.keys())) # O directamente print tuple(d.keys()) 
                           #porque las llaves no pueden repetirse.
# Lista de valores no repetidos
print list(set(d.values()))<jupyter_output><empty_output><jupyter_text>Ejercicio: elementos en común v3Se tiene una lista de diccionarios de alumnos * ¿Cómo se puede obtener los nombres no repetidos de los alumnos?<jupyter_code>alumnos = [{"nombre":"<NAME>", "rol":"2004001-7", 
            "ramos":["mate1", "progra", "fisica", "hum2"]},
           {"nombre":"<NAME>", "rol":"2004002-8", 
            "ramos":["mate1", "progra2"]},
           {"nombre":"<NAME>", "rol":"2004007-3", 
            "ramos":["mate1", "progra", "fisica", "hum1"]},
           {"nombre":"<NAME>", "rol":"2011001-4", 
            "ramos":["mate1", "progra", "progra2", "progra3"]},
           # ...
          ]
# Nombres no repetidos solucion
nombres_set = set()
for alumno in alumnos:
    # Alumno es un diccionario
    nombre_completo = alumno["nombre"]
    nombre_pila = nombre_completo.split(" ")[0]
    nombres_set.add(nombre_pila)
    
print nombres_set<jupyter_output>set(['Sebastian', 'Cesar', 'Maria'])<jupyter_text>Ejercicio: elementos en común v3Se tiene una lista de diccionarios de alumnos * ¿Cómo se puede obtener todos los ramos cursados?<jupyter_code>alumnos = [{"nombre":"<NAME>", "rol":"2004001-7", 
            "ramos":["mate1", "progra", "fisica", "hum2"]},
           {"nombre":"<NAME>", "rol":"2004002-8", 
            "ramos":["mate1", "progra2"]},
           {"nombre":"<NAME>", "rol":"2004007-3", 
            "ramos":["mate1", "progra", "fisica", "hum1"]},
           {"nombre":"<NAME>", "rol":"2011001-4", 
            "ramos":["mate1", "progra", "progra2", "progra3"]},
           # ...
          ]
# Ramos no repetidos
# Ramos no repetidos solucion
ramos_set = set()
for alumno in alumnos:
    # alumno es un diccionario
    lista_ramos = alumno["ramos"]
    ramos_set = ramos_set | set(lista_ramos)
    
print ramos_set<jupyter_output><empty_output><jupyter_text>Ejercicio de Certamen: C2 2S 2013El director técnico de la selección chilena le entrega como información una lista de tuplascon sus jugadores. Cada jugador viene representado por una tupla con la siguiente estructura:(nombre, informacion). A su vez, esta información es una tupla con la siguiente estructura:(posicion, goles, precio). Considere la siguiente estructura como ejemplo:<jupyter_code>jugadores = [
             #(nombre,(posicion,goles,precio))
             ('<NAME>',('delantero',8,14000000)),
             ('<NAME>',('central',3,4000000)),
             ('<NAME>',('arquero',1,300000)),
             ('<NAME>',('defensa',1,6000000)),
             ('<NAME>',('defensa',1,3000000)),
             ('<NAME>',('defenda',0,5000000)),
             ('<NAME>',('arquero',1,2000000)),
             ('<NAME>',('delantero',3,4000000))
            ]<jupyter_output><empty_output><jupyter_text>Ejercicio de C2 2S 2013a) Implemente la función jugadores_por_posicion(posicion,jugadores), la cual recibe como parámetro un string con la posición y la lista de tuplas de jugadores. Esta función debe retornar un conjunto con los nombres de los jugadores que se desempeñan en dicha posición:    print jugadores_por_posicion('delantero',jugadores)    {'<NAME>', '<NAME>'}    print jugadores_por_posicion('defensa',jugadores)    {'<NAME>', '<NAME>'}    print jugadores_por_posicion('arquero',jugadores)    {'<NAME>', '<NAME>'}<jupyter_code>def jugadores_por_posicion(posicion, jugadores):
    return

print jugadores_por_posicion('delantero',jugadores)
print jugadores_por_posicion('defensa',jugadores)
print jugadores_por_posicion('arquero',jugadores)
def jugadores_por_posicion(posicion, jugadores):
    jugadores_en_posicion = set()
    for jugador, (pos, gol, precio) in jugadores:
        if pos==posicion:
            jugadores_en_posicion.add(jugador)
    return jugadores_en_posicion

print jugadores_por_posicion('delantero',jugadores)
print jugadores_por_posicion('defensa',jugadores)
print jugadores_por_posicion('arquero',jugadores)<jupyter_output><empty_output><jupyter_text>Ejercicio de C2 2S 2013b) Implemente la función `cantidad_goles(nombre,jugadores)`, la cual recibe como parámetro un string con el nombre de un jugador y la lista de tuplas jugadores. Esta función debe retornar la cantidad de goles realizados por dicho jugador.    print cantidad_goles('<NAME>',jugadores)    8    print cantidad_goles('<NAME>',jugadores)    0<jupyter_code>def cantidad_goles(nombre, jugadores):
    return

print cantidad_goles('<NAME>',jugadores)
print cantidad_goles('<NAME>',jugadores)
print cantidad_goles('<NAME>',jugadores)
def cantidad_goles(nombre, jugadores):
    for jugador, (pos, gol, precio) in jugadores:
        if jugador==nombre:
            return gol
    # Si llegamos aqui, no encontramos el nombre
    print nombre, "no esta en la seleccion Chilena."
    return 0

print cantidad_goles('<NAME>',jugadores)
print cantidad_goles('<NAME>',jugadores)
print cantidad_goles('<NAME>',jugadores)<jupyter_output>8
0
<NAME> no esta en la seleccion Chilena.
0<jupyter_text>Ejercicio de C2 2S 2013c) Implemente la función `cantidad_goles_por_posicion(posiciones,jugadores)`, la cual recibe como parámetro un conjunto con las posiciones y la lista de tuplas jugadores. Este conjunto tiene la siguiente estructura:    posiciones = {'arquero','defensa','central','delantero'}La función retorna un diccionario cuyas claves son las posiciones de los jugadores y su valor lacantidad total de goles realizados por jugadores que se desempeñan en dicha posici on.    posiciones = {'arquero','defensa','central','delantero'}    print cantidad_goles_por_posicion(posiciones,jugadores)    {'defensa': 2, 'arquero': 2, 'central': 3, 'delantero': 11}<jupyter_code>def cantidad_goles_por_posicion(posiciones, jugadores):
    goles = {}
    for pos in posiciones:
        goles[pos] = 0
    for jugador, (pos, gol, precio) in jugadores:
        if pos in posiciones:
            goles[pos] += gol
    return goles

posiciones = {'defensa','central'}
print cantidad_goles_por_posicion(posiciones, jugadores)
def cantidad_goles_por_posicion(posiciones, jugadores):
    # Inicializar el diccionario vacio
    goles_por_posicion = {}
    for posicion in posiciones:
        goles_por_posicion[posicion] = 0
    # Llenar el diccionario
    for jugador, (pos, gol, precio) in jugadores:
        if pos in posiciones:
            goles_por_posicion[pos] += gol
    return goles_por_posicion

posiciones = {'arquero','defensa','central','delantero'}
print cantidad_goles_por_posicion(posiciones, jugadores)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14679499770837426, 'fraction_numerical': 0.026124533490473386, 'mean_word_length': 4.456948910325116, 'pattern_counts': {'":': 42, '<': 107, '<?xml version=': 0, '>': 94, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '597969', 'license': 'CC0-1.0', 'n_tokens_mistral': 6073, 'n_tokens_neox': 5874, 'n_words': 1522, 'path': 'ipynb/20-Conjuntos/Conjuntos.ipynb', 'repo_name': 'sebastiandres/iwi131', 'size': '15529'}