MAC2166 - Introdução à Computação

15/04/2014 - Aula 7

Problema Motivação

Escreva um programa que leia dois inteiros m e n e calcula

m!/(n!(m-n)!)

ou seja, um programa que calcule Cm,n -- quantas formas distintas é possível escolher n elementos de um grupo de m elementos.

Primeira tentativa de solução

In [ ]:
 
"""
comb1
primeira versão para calcular
m! / (n! (m - n)!)
"""
 
print("Cálculo de comb(m, n)")
m = int(input("Digite o valor de m:"))
n = int(input("Digite o valor de n:"))
 
fatm = 1
cont = 1
while cont <= m:
    fatm *= cont
    cont += 1
 
fatn = 1
cont = 1
while cont <= n:
    fatn *= cont
    cont += 1
 
fatmn = 1
cont = 1
while cont <= (m-n):
    fatmn *= cont
    cont += 1
 
comb = fatm / (fatn * fatmn)
print ("Comb(%d, %d) = %d"%(m, n, comb))

Solução

In [ ]:
 
"""
comb2
versão para calcular
m! / (n! (m - n)!)
 
usando funcao fat
"""
 
# DEFINICAO DAS FUNCOES
def fat(n):
    """(int) -> int
       fat recebe um inteiro n e devolve o fatorial de n
    """
    prod = 1
    cont = 1
    while cont <= n:
        prod *= cont
        cont += 1
    return prod
 
# PROGRAMA PRINCIPAL
 
print("Calculo de comb(m, n)")
m = int(input("Digite o valor de m:"))
n = int(input("Digite o valor de n:"))
 
comb = fat(m) / (fat(n) * fat(m-n))
print ("Comb(%d, %d) = %d"%(m, n, comb))

Logo no início da função fat que criamos, é possível ver um comentário de bloco. Esse tipo de comentário no início da função é chamado de docstring, e seu objetivo é documentar a função.

Um docstring deve conter a informação que é essencial de se saber para alguém que quer usar a função. Ele deve explicar de forma concisa o quê a função faz, mas sem entrar em detalhes sobre como isso é feito. Ele deve dizer o significado de cada parâmetro de entrada e também o seu tipo esperado (quando necessário). O docstring deve dizer também o que a função devolve como valor de retorno.

Podemos ver o docstring de uma função usando a função help, como no exemplo abaixo:

In [4]:
 
help(fat)
Help on function fat in module __main__:

fat(n)
    (int) -> int
    fat recebe um inteiro n e devolve o fatorial de n

Problema 13

Faça um programa que lê um numero inteiro n > 0 e imprime os coeficientes da expansão de (a+b)n .

In [ ]:
 
"""
comb3
mostra os coeficientes de (a + b) ** n
 
usando funcao fat e funcao comb
"""
 
# DEFINICAO DAS FUNCOES
def fat(n):
    """(int) -> int
       fat recebe um inteiro n e devolve o fatorial de n
    """
    prod = 1
    cont = 1
    while cont <= n:
        prod *= cont
        cont += 1
    return prod
 
# ------------------------------------------------------------
def comb(m, n):
    """(int, int) -> int
        comb recebe dois inteiros m e n e retorna a combinação de (m, n)
        mostra que devolve uma expressão
    """
    return fat(m) / (fat(n) * fat(m-n))
 
# PROGRAMA PRINCIPAL
 
print("Calculo dos coeficientes de (a + b) ** n")
n = int(input("Digite o valor de n:"))
 
cont = 0
while cont <= n:
    print("coef do termo a^(%d).b^(%d) = %d"%(n-cont, cont, comb(n, cont)))
    cont += 1
 

Problema 14

  • Usando a função sqrt(x) da biblioteca matemática da linguagem Python (import math), escreva uma função que recebe as coordenadas cartesianas de dois pontos no plano e devolve a distância entre os pontos.

  • Faça um programa que lê um ponto origem (x0, y0) e uma sequência de n>1 pontos e determina o ponto mais próximo do ponto origem.

In [ ]:
 
import math
 
# DEFINICAO DAS FUNCOES
def dist(x0, y0, x1, y1):
    dx = x0 - x1
    dy = y0 - y1
    return math.sqrt(dx*dx + dy*dy)
 
# PROGRAMA PRINCIPAL
x0 = float(input("Digite x0 (origem x): "))
y0 = float(input("Digite y0 (origem y): "))
 
n = int(input("Digite o número de pontos: "))
cont = 1
xmin = float(input("Digite x%d: ") %(cont))
ymin = float(input("Digite y%d: ") %(cont))
dmin = dist(x0, y0, xmin, ymin)
 
while cont < n:
    cont += 1
    x = float(input("Digite x%d: ") %(cont))
    y = float(input("Digite y%d: ") %(cont))
    d = dist(x0, y0, x, y)
    if d < dmin:
        dmin, xmin, ymin = d, x, y
 
print ("O ponto mais perto de (%5.2f, %5.2f) é (%5.2f, %5.2f) distante %5.2f."%(x0, y0, xmin, ymin, dmin))
 

Uma novidade que aparece na solução do problema 13 é o uso de um módulo de Python chamado math.

Um módulo é um arquivo que contém um conjunto de funções relacionadas. No módulo math, como o próprio nome sugere, temos funções matemáticas.

No problema 13, usamos uma função chamada sqrt; essa função recebe como parâmetro de entrada um número e devolve como valor de retorno o valor da raiz quadrada desse número. O valor devolvido pela sqrt é sempre um número do tipo float.

Antes de poder usar uma função de um módulo dentro do seu programa, você precisa indicar que o programa usará o módulo. Isso é feito por meio do comando import. Veja alguns exemplos de uso de funções da biblioteca math:

In [6]:
 
import math    # indica que o programa usará funções da biblioteca math
 
x = 9
y = math.sqrt(x)
print(y)
z = math.factorial(x)
print(z)
3.0
362880

Nos exemplos acima, é importante observar que para "fazer uma chamada à" (= executar a) uma função de um módulo, precisamos escrever o nome do módulo seguido de um ponto seguido do nome da função a ser executada (como em math.sqrt(2)).


Em aulas anteriores, vimos o comando de atribuição múltipla, que permite que um dado valor seja atribuído a mais de uma variável e um único comando (veja o exemplo abaixo):

num_cópia = num = int(input("Digite um número"))

Na solução do problema 13, há um novo tipo de atribuição múltipla:

dmin, xmin, ymin = d, x, y

Nesse tipo de atribuição, do lado esquerdo do operador = temos uma sequência n de variáveis separadas por vírgulas, enquanto que do lado direito de = temos uma sequência de n valores também valores separados por vírgulas, sendo que o primeiro valor será atribuído à primeira variável, o segundo valor será atribuído à segunda variável, e assim por diante.

Veja um outro exemplo a seguir:

In [7]:
 
a, b, c, d = 10, 20, 30, 40
print(a)
print(c)
10
30

Com esse tipo de atribuição, conseguimos trocar o valor de uma variável usando um único comando. Mas primeiro, veja a seguir um exemplo de uma sequência de comandos para trocar o valor de duas variáveis x e y da forma "tradicional" (ou seja, usando uma variável auxiliar):

In [9]:
 
x = 10
y = 20
 
# agora vamos trocar o valor das variáveis
z = x
x = y
y = z
 
print("x = ", x)
print("y = ", y)
x =  20
y =  10

Agora, veja o mesmo exemplo de troca de valores de variáveis usando atribuição múltipla:

In [10]:
 
x = 10
y = 20
 
# agora vamos trocar o valor das variáveis
x, y = y, x
 
print("x = ", x)
print("y = ", y)
x =  20
y =  10

Um outro exemplo interessante para o uso de atribuição múltipla é o de cálculo dos elementos da sequência de Fibonacci:

In [11]:
 
# Mostra os primeiros elementos da sequência de Fibonacci
# a soma de dois elementos consecutivos define o valor do próximo elemento
a, b = 0, 1
while b < 10:
    print(b)
    a, b = b, a+b
1
1
2
3
5
8

Problema Extra

  • Faça uma função que recebe um número inteiro n e devolve True se n é primo e devolve False em caso contrário.

  • Faça um programa que lê um número inteiro positivo m e verifica se m pode ser escrito como p+q, onde p e q são números primos.

In [ ]:
 
# DEFINICAO DAS FUNCOES
def primo(n):
    """(int) -> boolean
       primo recebe um inteiro n e devolve True se n é primo,
       e False no caso contrário.
     """
    # n é primo até que se prove o contrário
    é_primo = True
 
    # procure por um divisor de n entre 2 e n-1
    divisor = 2
    while divisor < n and é_primo:
        if n % divisor == 0:
            é_primo = False
        divisor += 1
 
    return é_primo
 
# PROGRAMA PRINCIPAL
m = int(input("Digite um numero: "))
i = 1
while i < m:
    if primo(i) and primo(m-i):
        print("%d = %d + %d" %(m,i,m-i))
 
    i += 1
    
 

Tópicos vistos na Aula 7

  • Introdução à criação de funções: comandos def e return
  • Documentando funções com docstring
  • Extra: "Bateries included" - import math

Referências e outros materiais para estudo