Exercícios de Exame
Nenhum exercício corresponde a esta pesquisa.
Condições e ciclos
Par ou ímpar decide a operaçãoCódigo
PE1, 2020/21
Escreve um programa em Python que lê três inteiros n1, n2 e n3 dados pelo utilizador. Se n1 for ímpar, o programa escreve o produto de n2 e n3. Se n1 for par, escreve a subtração entre n2 e n3.
n1 = int(input("n1? "))
n2 = int(input("n2? "))
n3 = int(input("n3? "))Verifica o código para comparar o resultado com os testes.
Testes
Ímpar dá produto
Entrada3 4 5
Esperado:20
Par dá subtração
Entrada2 4 5
Esperado:-1
3 4 5
20
2 4 5
-1
Solução
n1 = int(input("n1? "))
n2 = int(input("n2? "))
n3 = int(input("n3? "))
if n1 % 2 != 0:
print(n2 * n3)
else:
print(n2 - n3)O resto da divisão por 2 distingue par de ímpar: n1 % 2 != 0 é verdadeiro só quando n1 é ímpar. Cada ramo escreve a expressão pedida.
Persistência multiplicativaCódigo
PE1, 2020/21
A persistência multiplicativa de um inteiro positivo é o número de vezes que os seus dígitos podem ser multiplicados até o número ficar com um só dígito. Por exemplo, a persistência de 39 é 3, porque 39 → 3·9 = 27 → 2·7 = 14 → 1·4 = 4. Escreve um programa em Python que, dado um número num lido do utilizador, escreve a sua persistência multiplicativa.
num = int(input("num? "))
count = 0
print(count)Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Entrada39
Esperado:3
Um dígito
Entrada4
Esperado:0
Quatro passos
Entrada77
Esperado:4
39
3
4
0
77
4
Solução
num = int(input("num? "))
count = 0
while num > 9:
aux = 1
while num != 0:
aux = (num % 10) * aux
num = num // 10
num = aux
count += 1
print(count)O ciclo exterior conta um passo por multiplicação. O ciclo interior calcula o produto dos dígitos: num % 10 dá o último dígito e num // 10 o remove. O ciclo termina quando resta um só dígito (num <= 9).
Inverter um inteiro sem usar stringsCódigo
PE1, 2019/20
Escreve um programa em Python que, dado um inteiro num lido do utilizador, calcula o seu reverse (o número com os dígitos por ordem inversa) e o escreve. Não podes converter o número numa string nem manipular strings. Por exemplo, para num = 766 a saída é 667 e para num = 45654 a saída é 45654.
num = int(input("num? "))
rev = 0
print(rev)Verifica o código para comparar o resultado com os testes.
Testes
Três dígitos
Entrada766
Esperado:667
Palíndromo
Entrada45654
Esperado:45654
Zero
Entrada0
Esperado:0
766
667
45654
45654
0
0
Solução
num = int(input("num? "))
tmp = num
rev = 0
while tmp > 0:
d = tmp % 10
rev = rev * 10 + d
tmp = tmp // 10
print(rev)A cada passo, tmp % 10 extrai o último dígito e rev = rev * 10 + d acrescenta esse dígito à direita do número que está a construir. Para num = 0 o ciclo não corre e a saída é 0.
Converter quaternário para decimalCódigo
PE1, 2019/20
Um número quaternário (base 4) usa apenas os dígitos 0, 1, 2 e 3. Escreve um programa em Python que converte um número quaternário quat (base 4), lido do utilizador, no número decimal (base 10) correspondente. Por exemplo, para quat = 123 a saída é 27 e para quat = 112233 a saída é 1455.
quat = int(input("Quaternary number = "))
dec = 0
print(dec)Verifica o código para comparar o resultado com os testes.
Testes
Exemplo 123
Entrada123
Esperado:27
Exemplo 11
Entrada11
Esperado:5
Seis dígitos
Entrada112233
Esperado:1455
123
27
11
5
112233
1455
Solução
quat = int(input("Quaternary number = "))
dec = 0
power = 0
while quat:
last = quat % 10
dec += last * 4 ** power
quat //= 10
power += 1
print(dec)Cada dígito last vale last * 4^power, com a posição power a começar em 0. quat % 10 dá o dígito menos significativo e quat //= 10 avança para o seguinte.
Funções
Verificar número de ArmstrongCódigo
PE2, 2020/21
Escreve uma função em Python is_armstrong(n) que verifica se um número n de três dígitos é um número de Armstrong. Num número de Armstrong de três dígitos, a soma dos cubos de cada dígito é igual ao próprio número. A função devolve True ou False.
def is_armstrong(n):
return FalseVerifica o código para comparar o resultado com os testes.
Testes
153 é Armstrong
Código do testeprint(is_armstrong(153))Esperado:True
370 é Armstrong
Código do testeprint(is_armstrong(370))Esperado:True
123 não é Armstrong
Código do testeprint(is_armstrong(123))Esperado:False
print(is_armstrong(153))True
print(is_armstrong(370))True
print(is_armstrong(123))False
Solução
def is_armstrong(n):
soma = 0
aux = n
while aux > 0:
digit = aux % 10
soma += digit ** 3
aux //= 10
return soma == nPercorrem-se os dígitos de n com aux % 10 e aux //= 10, acumulando o cubo de cada um em soma. No fim, compara-se a soma com o número original. Para 153: 1 + 125 + 27 = 153.
Média móvel com vizinhança ímparCódigo
PE2, 2020/21
Escreve uma função em Python moving_average(alist, n) que, dada uma lista alist de inteiros e um inteiro ímpar n (a amplitude da vizinhança), devolve uma lista com as médias da vizinhança de cada número, arredondadas a duas casas decimais. Cada vizinhança tem exatamente n elementos. Se alist tiver comprimento menor que 3 ou se n < 3, o resultado é a lista vazia. Por exemplo, moving_average([1, 2, 3, 4, 5], 3) devolve [2.0, 3.0, 4.0].
def moving_average(alist, n):
return []Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(moving_average([1, 2, 3, 4, 5], 3))Esperado:[2.0, 3.0, 4.0]
Lista demasiado curta
Código do testeprint(moving_average([1, 2], 3))Esperado:[]
Vizinhança total
Código do testeprint(moving_average([1, 2, 3, 4, 5], 5))Esperado:[3.0]
print(moving_average([1, 2, 3, 4, 5], 3))[2.0, 3.0, 4.0]
print(moving_average([1, 2], 3))[]
print(moving_average([1, 2, 3, 4, 5], 5))[3.0]
Solução
def moving_average(alist, n):
if len(alist) < 3 or n < 3:
return []
avgs = []
for i in range(n // 2, len(alist) - n // 2):
left = alist[i - n // 2:i]
right = alist[i + 1:i + n // 2 + 1]
neighbors = left + right
avgs.append(round(sum(neighbors) / len(neighbors), 2))
return avgsSó os índices com n // 2 elementos de cada lado têm uma vizinhança completa, por isso o ciclo começa em n // 2 e termina antes de len(alist) - n // 2. A média usa os n - 1 vizinhos (o elemento central não entra), como no exemplo: (1+3)/2 = 2.0.
Dígitos por ordem decrescenteCódigo
PE2, 2019/20
Escreve uma função em Python order_digits(n) que, dado um inteiro n maior ou igual a zero, devolve um tuplo com os dígitos do número por ordem decrescente. Por exemplo, se n = 9013322 o resultado é o tuplo (9, 3, 3, 2, 2, 1, 0).
def order_digits(n):
return ()Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(order_digits(9013322))Esperado:(9, 3, 3, 2, 2, 1, 0)
Zero
Código do testeprint(order_digits(0))Esperado:(0,)
Dígito repetido
Código do testeprint(order_digits(500))Esperado:(5, 0, 0)
print(order_digits(9013322))(9, 3, 3, 2, 2, 1, 0)
print(order_digits(0))(0,)
print(order_digits(500))(5, 0, 0)
Solução
def order_digits(n):
if n == 0:
return (0,)
result = ()
for i in range(9, -1, -1):
aux = n
while aux > 0:
if aux % 10 == i:
result += (i,)
aux //= 10
return resultPara cada dígito possível de 9 até 0, percorre-se o número e acrescenta-se esse dígito ao tuplo uma vez por cada ocorrência. O caso n == 0 é tratado à parte porque o ciclo while nunca correria.
Strings
Trocar maiúsculas e minúsculasCódigo
PE3, 2020/21
Escreve uma função em Python swap_case(astr) que, dada uma string astr, devolve outra string com todas as letras minúsculas convertidas em maiúsculas e vice-versa. Por exemplo, swap_case("aBcD") devolve "AbCd".
def swap_case(astr):
return astrVerifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(swap_case('aBcD'))Esperado:AbCd
Símbolos não mudam
Código do testeprint(swap_case('Hello!'))Esperado:hELLO!
print(swap_case('aBcD'))AbCd
print(swap_case('Hello!'))hELLO!
Solução
def swap_case(astr):
result = ""
for letter in astr:
if letter.isupper():
result += letter.lower()
else:
result += letter.upper()
return resultPercorre-se a string letra a letra e constrói-se o resultado por concatenação, trocando a capitalização de cada letra. Caracteres que não são letras (como !) não são maiúscula nem minúscula e passam para o outro ramo, que os mantém inalterados.
Contar padrões de subcadeiasCódigo
PE2, 2019/20
Escreve uma função em Python subpatterns(astring) que recebe uma string astring e calcula quantas das suas subcadeias seguem um certo padrão. Uma subcadeia é um padrão quando o número de vezes que cresce é igual ao número de vezes que encolhe: num passo, a subcadeia cresce se o caráter for maior que o anterior e encolhe se for menor. Por exemplo, subpatterns("aghljcb") devolve a string "The string 'aghljcb' contains 3 substring patterns.".
def subpatterns(astring):
return ""Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(subpatterns("aghljcb"))Esperado:The string 'aghljcb' contains 3 substring patterns.
Sem padrões
Código do testeprint(subpatterns("ab"))Esperado:The string 'ab' contains 0 substring patterns.
print(subpatterns("aghljcb"))The string 'aghljcb' contains 3 substring patterns.
print(subpatterns("ab"))The string 'ab' contains 0 substring patterns.
Solução
def is_pattern(astring):
net = 0
for i in range(len(astring) - 1):
if astring[i + 1] > astring[i]:
net += 1
if astring[i + 1] < astring[i]:
net -= 1
return net == 0
def subpatterns(astring):
counter = 0
for step in range(2, len(astring) + 1):
for char_index in range(0, len(astring) - step + 1):
sub_str = astring[char_index:char_index + step]
if is_pattern(sub_str):
counter += 1
return "The string '{0}' contains {1} substring patterns.".format(
astring, counter)Uma subcadeia é padrão quando o saldo entre crescimentos (+1) e encolhecimentos (-1) é zero. Experimentam-se todas as subcadeias de comprimento pelo menos 2 e conta-se quantas têm saldo zero.
Dicionários e conjuntos
Valores únicos de uma lista de dicionáriosCódigo
PE3, 2020/21
Escreve uma função em Python unique_values(alist) que, dada uma lista de dicionários alist, devolve um conjunto com os valores de todos os dicionários. Por exemplo, unique_values([{"a": 1, "b": 2}, {"b": 2, "c": 3}]) devolve {1, 2, 3}.
def unique_values(alist):
return set()Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(unique_values([{'a': 1, 'b': 2}, {'b': 2, 'c': 3}]))Esperado:{1, 2, 3}Lista vazia
Código do testeprint(unique_values([]))Esperado:set()
print(unique_values([{'a': 1, 'b': 2}, {'b': 2, 'c': 3}])){1, 2, 3}print(unique_values([]))set()
Solução
def unique_values(alist):
uniqs = set()
for d in alist:
for v in d.values():
uniqs.add(v)
return uniqsPercorrem-se os valores de cada dicionário com d.values() e juntam-se todos a um conjunto, que elimina duplicados automaticamente.
Somar dicionáriosCódigo
PE4, 2020/21
Escreve uma função em Python sum_dicts(lst) que recebe uma lista lst de dicionários, cada um com um conjunto de chaves e valores inteiros, e devolve um único dicionário com todas as chaves presentes. Os valores associados à mesma chave são somados. Por exemplo, sum_dicts([{"a": 5, "b": 3}, {"a": 1, "c": 0}]) devolve {"a": 6, "b": 3, "c": 0}.
def sum_dicts(lst):
return {}Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(sum_dicts([{'a': 5, 'b': 3}, {'a': 1, 'c': 0}]))Esperado:{'a': 6, 'b': 3, 'c': 0}Chave só num dicionário
Código do testeprint(sum_dicts([{'x': 2}, {'y': 4}]))Esperado:{'x': 2, 'y': 4}
print(sum_dicts([{'a': 5, 'b': 3}, {'a': 1, 'c': 0}])){'a': 6, 'b': 3, 'c': 0}print(sum_dicts([{'x': 2}, {'y': 4}])){'x': 2, 'y': 4}Solução
def sum_dicts(lst):
result = {}
for d in lst:
for k, v in d.items():
result[k] = result.get(k, 0) + v
return resultPara cada par chave-valor, result.get(k, 0) devolve o valor acumulado ou 0 se a chave ainda não existe, e o valor novo é somado. Assim todas as chaves ficam no dicionário final.
Processar comandos sobre conjuntosCódigo
PE3, 2019/20
Escreve uma função em Python process(commands) que recebe uma lista commands a processar sobre conjuntos, pela ordem dada. Por exemplo, [{1, 3, 4}, "|", {2, 5}] deve ser convertido em {1, 2, 3, 4, 5}. As operações binárias disponíveis são "|" (união), "&" (interseção), "-" (diferença) e "x" (produto cartesiano, que devolve pares).
def process(commands):
return commands[0]Verifica o código para comparar o resultado com os testes.
Testes
União
Código do testeprint(process([{1, 3, 4}, '|', {2, 5}]))Esperado:{1, 2, 3, 4, 5}Diferença
Código do testeprint(process([{1, 3, 4}, '-', {3}]))Esperado:{1, 4}Interseção
Código do testeprint(process([{1, 2}, '&', {2, 3}]))Esperado:{2}
print(process([{1, 3, 4}, '|', {2, 5}])){1, 2, 3, 4, 5}print(process([{1, 3, 4}, '-', {3}])){1, 4}print(process([{1, 2}, '&', {2, 3}])){2}Solução
def process(commands):
s = commands[0]
for op, t in zip(commands[1::2], commands[2::2]):
if op == '|':
s = s | t
if op == '&':
s = s & t
if op == '-':
s = s - t
if op == 'x':
r = set()
for i in s:
for j in t:
r.add((i, j))
s = r
return sA lista alterna conjunto, operador, conjunto. commands[1::2] são os operadores e commands[2::2] os operandos seguintes; o zip emparelha-os e cada operador é aplicado ao acumulador s. O produto cartesiano constrói explicitamente o conjunto de pares.
Recursão
Contar elementos numa lista aninhadaCódigo
PE3, 2020/21
Escreve uma função em Python rec_count(alist) que calcula a frequência de cada elemento da lista aninhada alist (uma lista que pode conter listas, que por sua vez podem conter outras listas, e assim sucessivamente) e a devolve na forma de um dicionário. Por exemplo, rec_count([1, [2, [1, 2]], 3]) devolve {1: 2, 2: 2, 3: 1}.
def rec_count(alist):
return {}Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(rec_count([1, [2, [1, 2]], 3]))Esperado:{1: 2, 2: 2, 3: 1}Lista vazia
Código do testeprint(rec_count([]))Esperado:{}Repetidos em níveis diferentes
Código do testeprint(rec_count([5, [5]]))Esperado:{5: 2}
print(rec_count([1, [2, [1, 2]], 3])){1: 2, 2: 2, 3: 1}print(rec_count([])){}print(rec_count([5, [5]])){5: 2}Solução
def rec_count(alist):
result = {}
for el in alist:
if type(el) != list:
d = {el: 1}
else:
d = rec_count(el)
for k, v in d.items():
result[k] = result.get(k, 0) + v
return resultSe o elemento não é uma lista, conta-se como uma ocorrência ({el: 1}); se for, conta-se recursivamente a sublista. Depois de cada chamada recursiva, os pares do dicionário devolvido são somados ao acumulador result.
Contar dígitos recursivamenteCódigo
PE3, 2019/20
Escreve uma função em Python count_digits(n) que calcula a frequência de cada dígito do número n, com n > 0, e a devolve na forma de um dicionário. Não podes usar ciclos nem variáveis globais. Por exemplo, count_digits(12321) devolve {1: 2, 2: 2, 3: 1}.
def count_digits(n):
return {}Verifica o código para comparar o resultado com os testes.
Testes
Exemplo do enunciado
Código do testeprint(count_digits(12321))Esperado:{1: 2, 2: 2, 3: 1}Um dígito
Código do testeprint(count_digits(5))Esperado:{5: 1}
print(count_digits(12321)){1: 2, 2: 2, 3: 1}print(count_digits(5)){5: 1}Solução
def count_digits(n):
if n == 0:
return {}
d = count_digits(n // 10)
d[n % 10] = d.get(n % 10, 0) + 1
return dO caso base é n == 0, que devolve o dicionário vazio. A chamada recursiva trata do número sem o último dígito e, no regresso, esse dígito é contado no dicionário devolvido. Assim cada dígito é processado uma vez, sem ciclos.
Calculadora de fraçõesCódigo
PE3, 2020/21
Escreve uma função em Python calculator(expr) que calcula o valor de uma expressão expr. A expressão pode ser uma fração representada por um tuplo (numerador, denominador) ou um tuplo da forma (expr, operador, expr). Os únicos operadores válidos são a multiplicação "*" e a divisão "/", e todos os valores são não negativos. Simplifica o resultado à menor fração inteira. Por exemplo, calculator(((1, 3), "*", (2, 5))) calcula 1/3 · 2/5 e devolve (2, 15).
def calculator(expr):
return exprVerifica o código para comparar o resultado com os testes.
Testes
Multiplicação do enunciado
Código do testeprint(calculator(((1, 3), '*', (2, 5))))Esperado:(2, 15)
Divisão simplificada
Código do testeprint(calculator(((1, 2), '/', (1, 4))))Esperado:(2, 1)
Expressão aninhada
Código do testeprint(calculator((((1, 2), '*', (1, 3)), '/', (1, 6))))Esperado:(1, 1)
print(calculator(((1, 3), '*', (2, 5))))(2, 15)
print(calculator(((1, 2), '/', (1, 4))))(2, 1)
print(calculator((((1, 2), '*', (1, 3)), '/', (1, 6))))(1, 1)
Solução
def mdc(x, y):
while y:
x, y = y, x % y
return x
def calculator(expr):
if len(expr) == 2:
num, den = expr
else:
e1, op, e2 = expr
e1 = calculator(e1)
e2 = calculator(e2)
if op == '*':
num, den = e1[0] * e2[0], e1[1] * e2[1]
else:
num, den = e1[0] * e2[1], e1[1] * e2[0]
d = mdc(num, den)
return (num // d, den // d)O caso base é um tuplo de dois elementos (a fracción). Num tuplo de três, calculam-se recursivamente as duas subexpressões e aplicam-se as regras: multiplicam-se numeradores com numeradores e denominadores com denominadores; na divisão, cruza-se. No fim, divide-se pelo máximo divisor comum para simplificar.
Geradores
Gerador de FibonacciCódigo
PE4, 2020/21
Escreve uma função geradora em Python fib(start, end) que gera a sequência de Fibonacci de inteiros começando no start-ésimo número (start >= 1) e acabando no end-ésimo número (end >= start). Os dois primeiros números da sequência são 1 e cada número consecutivo é a soma dos dois anteriores. Por exemplo, se start = 1 e end = 7, a sequência gerada é [1, 1, 2, 3, 5, 8, 13].
def fib(start, end):
returnVerifica o código para comparar o resultado com os testes.
Testes
Sequência completa
Código do testeprint(list(fib(1, 7)))Esperado:[1, 1, 2, 3, 5, 8, 13]
A meio da sequência
Código do testeprint(list(fib(4, 6)))Esperado:[3, 5, 8]
print(list(fib(1, 7)))[1, 1, 2, 3, 5, 8, 13]
print(list(fib(4, 6)))[3, 5, 8]
Solução
def fib(start, end):
i = 1
a, b = 1, 1
while i <= end:
if i >= start:
yield a
a, b = b, a + b
i += 1A sequência tem de ser calculada desde o início, independentemente de start, por isso o contador i começa em 1. Só se faz yield quando i >= start, e a, b = b, a + b avança dois termos de cada vez.
Gerador a partir de uma lista de intervalosCódigo
PE4, 2019/20
Uma lista de intervalos é uma lista de tuplos que representam intervalos. Cada tuplo representa um intervalo da forma (min, max). Os tuplos aparecem por ordem crescente na lista e os intervalos são disjuntos. Por exemplo, a lista [(1, 1), (3, 5), (10, 15)] representa a sequência completa 1, 3, 4, 5, 10, 11, 12, 13, 14, 15. Escreve uma função geradora generator(intlist) que vai devolvendo com yield o termo seguinte da sequência completa representada em intlist.
def generator(intlist):
returnVerifica o código para comparar o resultado com os testes.
Testes
Dois intervalos
Código do testeprint(list(generator([(1, 1), (3, 5)])))Esperado:[1, 3, 4, 5]
Intervalo com vários termos
Código do testeprint(list(generator([(10, 12)])))Esperado:[10, 11, 12]
print(list(generator([(1, 1), (3, 5)])))[1, 3, 4, 5]
print(list(generator([(10, 12)])))[10, 11, 12]
Solução
def generator(intlist):
while intlist != []:
yield intlist[0][0]
if intlist[0][0] == intlist[0][1]:
intlist = intlist[1:]
else:
intlist = [(intlist[0][0] + 1, intlist[0][1])] + intlist[1:]Em cada passo, o primeiro valor do primeiro intervalo é devolvido com yield. Se min == max, o intervalo está esgotado e passa-se ao seguinte; senão, incrementa-se o min do primeiro intervalo, avançando para o próximo termo.