In [1]:
# ignore esse código inicial, é apenas para preparar a página
from IPython.display import YouTubeVideo, HTML, Image, display
css_file = './modelo.css'
HTML(open(css_file, "r").read())


Out[1]:

Introdução à Programação em Python

Manipulação de Listas

Anteriormente, vimos alguns exemplos de criação e manipulação de listas:

lista = [1,2,3,4,5]
print(lista[0])

Também vimos uma forma de criar listas de inteiros com a função range():

lista = list(range(1,11))
print(lista # [1,2,3,4,5,6,7,8,9,10])

Para acessar um elemento em uma lista fazemos:

print(lista[0]) # primeiro elemento
print(lista[-1]) # último elemento

E para uma faixa de valores:

print(lista[0:3]) # elemento 0, 1 e 2
print(lista[5:2:-1]) # do 5 ao 3, de -1 em -1

In [2]:
lista = list(range(1,11))
print(lista) # [1,2,3,4,5,6,7,8,9,10]
print(lista[0]) # primeiro elemento
print(lista[-1]) # último elemento
print(lista[0:3]) # elemento 0, 1 e 2
print(lista[5:2:-1]) # do 5 ao 3, de -1 em -1


[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
10
[1, 2, 3]
[6, 5, 4]

Podemos também alterar um elemento de uma lista utilizando os índices:


In [3]:
lista[0] = 0
print(lista)


[0, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Os operadores + e * tem a função de concatenação e repetição:


In [4]:
print(list(range(0,5)) + list(range(5,10)))
print([1,2,3]*2)


[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 1, 2, 3]

Para adicionar um elemento ao final da lista temos o comando append, que utilizado como mostrado a seguir:


In [5]:
print(lista)
lista.append(11)
print(lista)


[0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Para remover um elemento, utilizamos o comando del:


In [6]:
print(lista)
del lista[2] # remove o elemento na posição 2
print(lista)


[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[0, 2, 4, 5, 6, 7, 8, 9, 10, 11]

O tamanho de uma lista pode ser obtido com o comando len:


In [7]:
print(len(lista))


10

E podemos verificar se um certo elemento existe na lista com o comando in:


In [8]:
print(10 in lista)
print(3 in lista)


True
False

Digamos que queremos efetuar uma operação para cada elemento dessa lista.

Por exemplo, imprimir o quadrado dos valores de um número:

Para cada x em lista:
    print (x*x)

Para isso o Python utiliza a instrução for da seguinte maneira:


In [9]:
for x in lista:
    print(x*x)


0
4
16
25
36
49
64
81
100
121

A instrução for é outra estrutura de repetição que permite repertimos uma operação para cada elemento de uma lista ou por um determinado número de vezes.

Vamos criar uma função para calcular a soma dos N primeiros números, começando do 1.


In [10]:
def Soma(N):
    soma = 0
    for x in range(1,N+1):  # é um intervalo aberto [a,b[
        soma = soma + x
    return soma

print (Soma(5))
print (Soma(10))


15
55

Podemos utilizar o comando for para criar listas diferentes das geradas pelo comando range():


In [11]:
listaQuad = []
for x in range(1,11):
    listaQuad.append(x*x)  # cria a lista dos números de 1 a 10 ao quadrado
print (listaQuad)


[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

FizzBuzz: crie uma função que imprima os números de 1 até N substituindo certos números com a seguinte regra:

  • Se o número for múltiplo de 3, imprima Fizz
  • Se o número for múltiplo de 5, imprima Buzz
  • Se o número for múltiplo de 3 e 5, imprima FizzBuzz

In [15]:
def FizzBuzz(N):

    
    
    
    
FizzBuzz(10)


1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz

Potência: Crie uma função que calcule $y^b$, dados $y$ e $b$, repetindo a multiplicação de $y$ por $y$ $b$ vezes.

$3^4 = 3*3*3*3$

Uma forma de pensar na resolução desse problema é reduzi-lo para um caso simplificado.

Vamos tomar o exemplo anterior, $3^4$, podemos dizer que:

$$3^4 = 3^3 * 3$$

Agora nosso problema se reduziu em descobrir o valor de $3^3$ bastanto multiplicar $3$ nesse resultado.

Seguindo o raciocínio temos:

$$3^4 = 3^3 * 3 = (3^2 * 3) * 3 = (( 3^1 * 3) * 3) * 3 = 3*3*3*3$$

Então iniciando com o valor $3$, basta multiplicarmos sucessivamente por $3$ por $b-1$ vezes.


In [19]:
def Potencia(y,b):
    """
    Calcula y^b
    """

    
    
    
print (Potencia(3,4), 3**4)


81 81

Monte Carlo: Na ciência experimental temos que realizar experimentos e medições para estimar certos valores. Ex.:

  • Distribuição da altura dos alunos
  • Relação entre Altura dos alunos e CR
  • Velocidade média do vôo de uma andorinha

Porém, em certas ocasiões o custo de uma medição é elevado ou impossibilitado. Em muitos casos, o computador pode nos ajudar fazendo simulações.

Simulações Computacionais são simulações realizadas em um computador para reproduzir o comportamento de um sistema.

A simulação utiliza um abstrato que aproxima o comportamento real.

Uma técnica de simulação é conhecida como Monte Carlo em que medições aleatórios, seguindo certa distribuição, são realizadas.

Vamos exemplificar com um jogo de dardos.

Primeiro vamos plotar uma circunferência de raio $0.5$, para isso precisamos definir uma função que retorne o lado superior e outra para o lado inferior:

$$ \pm \sqrt{0.25 - (x-0.5)^{2}} + 0.5 $$

In [27]:
# Biblioteca matemática
import math

# Retorna parte superior e inferior da circunferencia
def Circ(x):
    return math.sqrt(0.25 - (x - 0.5)**2) + 0.5

def CircNeg(x):
    return -math.sqrt(0.25 - (x - 0.5)**2) + 0.5

Agora criaremos uma função PlotaCirculo() que desenha uma circunferência na área de plotagem atual.


In [31]:
# Biblioteca de plotagem
%matplotlib inline
import matplotlib.pyplot as plt
from numpy import arange

def PlotaCirculo():
    # vamos fazer uma lista com valores de 0 até 1, de 0.01 em 0.01
    Xc = arange(0,1.01,0.01)
        
    # Vamos aplicar as funções Circ e CircB nessa lista
    Y1 = list(map(Circ, Xc))
    Y2 = list(map(CircNeg, Xc))
    
    # Agora plota cada parte da circunferência com o comando plot
    plt.plot(Xc,Y1, color='blue')    
    plt.plot(Xc,Y2, color='blue')

In [32]:
# configura a área de plotagem
plt.figure(figsize=(5,5))  
plt.axis([-0.1, 1.1, -0.1, 1.1])
plt.style.use('fivethirtyeight')
plt.hold(True)  # indica que queremos plotar várias figuras na mesma área    
PlotaCirculo()


Agora vamos criar uma função PlotaAlvo(X, Y) que recebe uma lista de pontos X e Y para plotar.


In [34]:
def PlotaAlvo(X,Y):
    # Prepara área de plotagem
    plt.figure(figsize=(5,5))  
    plt.axis([-0.1, 1.1, -0.1, 1.1])
    plt.style.use('fivethirtyeight')
    plt.hold(True)
    PlotaCirculo()
    
    # Se existirem pontos X e Y, plota eles
    if len(X) > 0 and len(Y) > 0:
        plt.plot(X,Y,'.', color='red') # o '.' indica que não quero ligar os pontos na plotagem
    plt.show()

PlotaAlvo([],[])


O alvo pode ser definido como um círculo inscrito em um quadrado de tamanho 1 x 1.

Se atirarmos os dardos aleatoriamente, teremos a mesma chance de atingir qualquer ponto dentro do quadrado.

Se atirarmos dardos suficientes, cobriremos o quadrado por completo.

Contando quantos dardos caíram dentro do círculo, podemos estimar a área dele.

Tendo a área do círculo e do quadrado temos que:

$$ Ac = \pi r^2 \\ Aq = L^2 = (2r)^2 = 4r^2 \\ \frac{Ac}{Aq} = \frac{\pi}{4} \\ \pi = 4\frac{Ac}{Aq} $$

O algoritmo de Monte Carlos funciona da seguinte forma:

dentro = 0
Para i na faixa de 0 a N:
    x, y = GeraPontos()

    Se DentroCirc(x, y):
        dentro = dentro + 1

retorna 4 * dentro / N

Sendo dentro uma variável utilizada para contar quantos pontos estão dentro da Circunferência.

A função GeraPontos() gera dois pontos aleatórios e DentroCirc(x,y) checa se o ponto (x,y) está dentro da circunferência.


In [42]:
import random

def GeraPontos():
    return random.random(), random.random()

def DentroCirc(x,y):
    return (x-0.5)**2 + (y-0.5)**2 <= 0.25

In [43]:
def MonteCarlo(N):
    X = []
    Y = []
    dentro = 0
    for i in range(N):
        x, y = GeraPontos()
        X.append(x)
        Y.append(y)
        
        if DentroCirc(x,y):
            dentro = dentro + 1
            
    return 4*dentro/N, X, Y

In [44]:
pi, X, Y = MonteCarlo(1000)
print ("O valor de pi é ", pi)
PlotaAlvo(X,Y)


O valor de pi é  3.192

Opcional

Syntactic Sugar: Podemos criar uma lista utilizando uma notação mais próxima da matemática:

ListaQuad = [ x*x for x in range(1,101)]

Esse formato de geração de lista é conhecido como list comprehension e pode ser combinado com instruções condicionais:

ListaQuadImpar = [x*x for x in range(1,101) if (x*x) % 2 == 1]

In [42]:
ListaQuad = [ x*x for x in range(1,11)]
ListaQuadImpar = [x*x for x in range(1,11) if (x*x) % 2 == 1]

print (ListaQuad)
print (ListaQuadImpar)


[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 9, 25, 49, 81]

O comando sum() calcula a somatória dos elementos numéricos de uma lista.

O comando zip(Lista1, Lista2) cria uma lista de duplas combinando as duas listas passadas como parâmetros.


In [30]:
X = [1,2,3]
Y = [4,5,6]
print(list(zip(X,Y)))

for x,y in zip(X,Y):
    print(x+y)
    
print (sum(X), sum(Y))


[(1, 4), (2, 5), (3, 6)]
5
7
9
6 15

In [45]:
def MonteCarlo(N):
    dentro = 0
    X=[random.random() for _ in range(N)]
    Y=[random.random() for _ in range(N)]
    pontosDentro = [1 for x,y in zip(X,Y) if DentroCirc(x,y)]
    pi = 4.0*sum( pontosDentro)/N
    return pi, X, Y 

pi, X, Y = MonteCarlo(1000)
print ("O valor de pi é ", pi)
PlotaAlvo(X,Y)


O valor de pi é  3.164