Matemática:

Exercício 01: Crie uma função que determine se um número é um palíndromo.

Por definição, um número palíndromo é aquele que, ao inverter seus dígitos ele permanece igual. Ex.:

$$12321, 535, 212,$$

Crie primeiro uma função que receba um número $x$ como parâmetro e retorne esse número invertido. Faça primeiro o procedimento passo a passo no papel.


In [1]:
print (Palindromo(1221))
print (Palindromo(121))
print (Palindromo(1231))


True
True
False

Exercício 02: Crie uma função Fatorial() que calcule n!.

$$n! = n \cdot (n-1) \cdot (n-2) \dots 1$$

Pense primeiro nos casos $0!$ e $1!$ antes de criar o algoritmo.


In [26]:
print (Fatorial(0))
print (Fatorial(1))
print (Fatorial(5))
print (Fatorial(10))


1
1
120
3628800

Exercício 03: Crie uma função para calcular o $n$-ésimo termo da sequência de Fibonacci.

A sequência de Fibonacci é definida por:

$$ F_0 = F_1 = 1 \\ F_n = F_{n-1} + F_{n-2} $$

In [5]:
for i in range(10):
    print (Fibonacci(i),)
print()


0 1 1 2 3 5 8 13 21 34
0 1 1 2 3 5 8 13 21 34

Exercício 04: Crie uma função SomaSerie() que efetue a soma $S$ das seguintes séries para um valor de $n$:

$$ S_1 = 1 + \frac{1}{3} + \frac{1}{5} + \dots + \frac{1}{2n+1} \\ S_2 = \frac{1}{2} + \frac{1}{4} + \dots + \frac{1}{2n} \\ S = S_1 - S_2 $$

In [8]:
print (SomaSeries(3))
print (SomaSeries(10))
print (SomaSeries(100))


0.0928571428571
0.0446950710109
0.00494974495575

Exercício 05: Crie 2 funções para calcular o Coeficiente Binomial:

$$\binom nk = \frac{n!}{k!\,(n-k)!} \quad \text{for }\ 0\leq k\leq n.$$

Na primeira versão, utilize a função fatorial do Exercício 02.

Na segunda versão, tente simplificar ao máximo a equação para reduzir o número de operações efetuadas.


In [25]:
print (Binomial1(4,2), Binomial2(4,2))
print (Binomial1(10,4), Binomial2(10,4))


6 6
210 210

Simulação

Exercício 06: Crie uma função para verificar o paradoxo de Monty Hall.

O Paradoxo de Monty Hall mostra como o cálculo de probabilidades pode ser contra-intuitivo.

Monty Hall é um programa de auditório em que, em um dos jogos, o particpante deve escolher uma entre três portas.

Uma dessas portas contém um carro, as outras duas, uma cabra.

Após o participante realizar a escolha, o apresentador abre uma das duas outras portas revelando uma cabra. Então ele pergunta: "Você gostaria de mudar de porta?".

Qual a escolha que tem maior probabilidade de vitória? Manter a escolha atual ou mudar de porta?

O paradoxo diz que, inicialmente ao escolher uma das portas a probabilidade de acertar é 1/3, e a de errar 2/3. Após ser revelado uma das portas erradas, as probabilidades se mantêm, então ao mudar de porta ele terá probabilidade de 2/3 de vitória.

Faça uma função que simule $n$ partidas desse jogo, mantendo a escolha de porta inicial e $n$ partidas alterando a porta. Estime a probabilidade de vitória nos dois casos.

Para simular o sorteio de qual porta tem o prêmio e qual porta o participante escolhe, utilize a função randint(a,b) da biblioteca random. Essa função retorna um número aleatório $n$ tal que $a \leq n \leq b$.


In [12]:
import random












print(MontyHall(100))


(0.27, 0.7)

Avançados

Exercício 07: Dado um número $x$, crie a função Segmenta() que divida esse número em segmentos de $d$ dígitos. Ex.:

$$ x = 123456 \\ d = 2 \\ [12,34,56] $$

Note que é mais fácil extrair os $d$ dígitos da direita para a esquerda. Nesse caso, crie também uma função Inverte() que gera o inverso de um número.

Crie então uma outra função chamada Crescente() que verifica se a lista de valores estão em ordem crescente.

Finalmente, crie uma função que verifique qual o menor valor de $d$ que gera um segmento de números crescentes.


In [23]:
print (MenorD(131145))


(3, [131, 145])

Exercício 08: Faça uma função que gere o triângulo de Pascal.

Ele é composto por $N$ listas, sendo que cada lista $i$ tem tamanho $i+1$ com $i=0 \dots N-1$.

O elemento da linha $i$ e coluna $j$ pode ser calculado através do coeficiente binomial $\binom{i}{j}$ ou somando os elementos $i-1,j-1$ com $i-1,j$, assumindo $0$ quando fora do limite.

Para armazenar o triângulo, você terá que criar lista de listas. Ex.:


In [29]:
lista = [] # lista vazia
lista.append( [0,1]) # insere uma lista dentro da lista
print (lista)

lista.append([2,3,4])
print (lista)

print (lista[0])
print (lista[1][2])


[[0, 1]]
[[0, 1], [2, 3, 4]]
[0, 1]
4

In [28]:
for l in Pascal(5):
    print (l)


[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]

Exercício 09: Um Fractal é uma imagem com padrões auto-similares. Uma forma de desenhar um fractal é através do Conjunto Julia, que trabalha com números complexos. Podemos construir uma matriz com valores do conjunto de Julia da seguinte forma:

m = []
Para i de -1.5 até 1.5 com passo p:
    l = []
    Para j de 1.0 até -1.0 com passo -p:
        l.append( Julia( complex(i,j), c ) )
     m.append(l)

Para percorrermos os valores em uma faixa de números reais, podemos utilizar o comando arange() da biblioteca numpy:

import numpy as np
m = []
for i in np.arange(-1.5,1.5,p):
    l = []
    for j in np.arange(1.0,-1.0,-p):
        l.append( Julia( complex(i,j), c ) )
     m.append(l)

Ou usando syntatic sugar:

m = [ [Julia(complex(i,j),c) for j in np.arange(1.0,-1.0,-step)] for i in np.arange(-1.5,1.5, step) ]

O comando complex() cria um número complexo através dos valores passados como parâmetro. A variável $c$ é um número complexo de base passada como parâmetro.

A função Julia(x,y) é definida como:

  • Para n em range(200)
  • se o valor absoluto de x for maior que 4, retorne n
  • senão, faça x = x*x + y
  • ao final das repetições, retorne n

Implemente a função Julia(x,y) e a função GeraFractal(c, passo ) que recebe o número complexo semente e o tamanho do passo.

Essa função deve gerar a tal matriz m, os comandos para plotagem já são dados!

Não utilize um passo menor que 0.005, pois poderá ocupar muita memória do computador.

Experimente com diversos valores de $c$.


In [3]:
%pylab inline
import matplotlib.pylab as plt
import numpy as np

def Julia(x,y):
    ...
    return n


def GeraFractal( c, step ):    
    m = [ [Julia(complex(i,j),c) for j in np.arange(1.0,-1.0,-step)] for i in np.arange(-1.5,1.5, step) ]    
    fig = plt.figure(figsize=(15,15))
    plt.imshow(m, cmap="RdGy", extent=[-2,2,-2,2])

GeraFractal(-0.06+0.67j, 0.005)


Populating the interactive namespace from numpy and matplotlib
WARNING: pylab import has clobbered these variables: ['plt']
`%matplotlib` prevents importing * from pylab and numpy

Exercício 10: A música We Will Rock You do grupo Queen inovou na criação de uma técnica de mixagem hoje conhecida como reverberação não-harmônica.

Para criar o efeito de uma multidão, o guitarrista e físico Brian May, gravou o efeito de batida e multiplicou essas batidas com pequenos atrasos.

Para evitar que as múltiplas cópias se sobrepusessem, ele fez com que os atrasos fossem múltiplos de números primos.

Vamos utilizar para essa tarefa as bibliotecas wave e audioop do Python e o som Palmas.wav fornecido no site do curso.

A primeira tarefa é criar uma função Primo(n) que verifica se o número $n$ é primo.

A segunda tarefa é completar a função GeraMusica( ecos ) que gera $n$ repetições do som contido no arquivo, com $n$ sendo a quantidade de números primos de 1 até ecos.


In [288]:
import wave, audioop







def GeraMusica( ecos ):
    
    # abre o arquivo fornecido
    som1 = wave.open('Palmas.wav')
    # criar o arquivo destino, o segundo parâmetro 'w'
    # indica que o arquivo vai ser aberto para escrita
    som2 = wave.open('WeWillRockYou.wav', 'w')

    # faz com que o som criado tenha os mesmos parâmetros do som original
    som2.setnchannels( som1.getnchannels() )
    som2.setsampwidth( som1.getsampwidth() )
    som2.setframerate( som1.getframerate() )

    # lê o arquivo de audio e normaliza o som
    frames = som1.readframes( som1.getnframes() )
    taxa = 0x7fff/ audioop.max(frames, som1.getsampwidth())    
    frames = audioop.mul(frames, som1.getsampwidth(), taxa)


    # gera uma lista de números primos de 1 até ecos
    primos = ???
    
    # o som está em 44100Hz com apenas 1 canal, isso significa
    # que cada decimo de segundo contem 44100/10 posições da lista
    # cada eco será colocado com atraso de mult*p, onde p é cada número primo
    mult = som1.getframerate()*som1.getnchannels()/10
    
    # cada eco tem um decaimento de amplitude
    decaimento = 0.3

    # para cada numero primo
    for p in primos:
        # a partir de onde começaremos a colocar o eco
        atraso = ???
        
        # frame2 será o trecho que copiaremos para o eco
        # ele sera o conteúdo da lista frames do elemento 0 até len()-atraso
        frame2 = ???
        
        # Vamos multiplicar frame2 pelo decaimento, para reduzir o som
        frame2 = audioop.mul( frame2, som1.getsampwidth(), decaimento)
        
        # frame2 será adicionado a frames a partir do atraso
        # utilize a função audioop.add( frame1, frame2, som1.getsampwidth() )
        frame1 = ???
        frame2 = audioop.add( frame1, frame2, som1.getsampwidth())
        
        # concatene frames de 0 até atraso com frame2
        frames = ???
        
        # reduza o decaimento pela metade
        decaimento = ???


    # grava o novo som
    som2.writeframes( frames )

    som1.close()
    som2.close()

GeraMusica(100)

In [ ]: