0% acharam este documento útil (0 voto)
23 visualizações9 páginas

FP2021E1 Sample

Enviado por

Hugo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
23 visualizações9 páginas

FP2021E1 Sample

Enviado por

Hugo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 9

Fundamentos da Programação

Ano lectivo 2020-21


Primeiro Exame
3 de Fevereiro de 2021

Pergunta 1 (val. 2)
Considere a linguagem cujas frases começam pelo sı́mbolo ’a’, o qual é seguido por um número
par de ocorrências de um dos sı́mbolos ’b’, ’c’, ’d’, após o que terminam com o sı́mbolo ’e’.
Por exemplo ’abcddcde’ e ’abcdbcdbcdbcde’ são frases da linguagem; ’ae’ e ’ababe’ não o são.
a) Escreva uma gramática em notação BNF para a linguagem apresentada.
<f r a s e > : : = a <par> e
<par> : : = <char> <char> | <char> <char> <par>
<char> : : = b | c | d
b) Escreva o predicado reconhece que recebe como argumento uma cadeia de caracteres e
devolve verdadeiro apenas se a cadeia de caracteres pertence à linguagem. O predicado gera
um erro se o seu argumento não for uma cadeia de
def r e c o n h e c e ( s e q ) :
return type ( s e q ) == s t r and len ( s e q ) % 2 == 0 \
and len ( s e q ) > 3 and s e q [ 0 ] == ’ a ’ and s e q [ −1] == ’ e ’ \
and a l l ( [ ch in ’ bcd ’ for ch in s e q [ 1 : − 1 ] ] )

Pergunta 2 (val. 1.5)


Escreva uma função que recebe um número inteiro positivo e que calcula uma codificação para
esse número do seguinte modo:
• a ordem dos algarismos do número é invertida;

• cada algarismo ı́mpar é substituı́do pelo ı́mpar seguinte, entendendo-se que o ı́mpar
seguinte a 9 é 1;

• cada algarismo par é substituı́do pelo par anterior, entendendo-se que o par anterior a
0 é 8.
Caso o argumento não esteja correto, deverá gerar um erro com o texto ’Argumento invalido’.
Por exemplo:
>>> codifica(1234567890)
8169472503

def c o d i f i c a (num ) :
i f not ( type (num)==int and num>=0):
r a i s e Val ueErro r ( ’ Argumento i n v a l i d o ’ )
novo num = 0
while num > 0 :

1
d i g = num % 10
i f d i g % 2 == 0 : # par
d i g = ( d i g − 2 ) % 10
e l s e : # impar
d i g = ( d i g + 2 ) % 10
novo num = novo num ∗ 10 + d i g
num = num // 10
return novo num

Pergunta 3 (val. 2)
Suponha que existe a função de um argumento n esimo primo, que recebe um número nat-
ural e devolve o número primo cuja posição corresponde ao seu argumento. Por exemplo
n esimo primo(1) devolve 2, n esimo primo(2) devolve 3, n esimo primo(3) devolve 5, e assim
sucessivamente.
(a) Escreva a função codifica palavra que recebe como argumento uma palavra e devolve
a codificação dessa palavra usando os números de Gödel. Uma palavra com n letras (le-
tra 1 letra 2 ... letra n) codificada usando os números de Gödel corresponde ao inteiro
2**ord(letra 1)*3**ord(letra 2)* ... *n esimo primo(n)**ord(letra n). Por exemplo a palavra
‘dia’ é codificada como 2**ord(‘d’)*3**ord(‘i’)*5**ord(‘a’). Não é necessário validar o argu-
mento da sua função.
def c o d i f i c a p a l a v r a ( p a l a v r a ) :
res = 1
seq = 1
for ch in p a l a v r a :
r e s ∗= n e s i m o p r i m o ( s e q ) ∗∗ ord ( ch )
s e q += 1
return r e s
(b) Escreva a função descodifica palavra que recebe como argumento um natural correspon-
dente a uma palavra codificada usando os números de Gödel e devolve a palavra original. Não
é necessário validar os dados de entrada
def d e s c o d i f i c a p a l a v r a ( n a t u r a l ) :
res = ’ ’
seq = 1
while n a t u r a l > 1 :
primo = n e s i m o p r i m o ( s e q )
ch = 0
while n a t u r a l % primo == 0 :
ch += 1
n a t u r a l //= primo
r e s += chr ( ch )
s e q += 1
return r e s

2
Pergunta 4 (val. 1)
Escreva a função duplica elementos pares que recebe uma lista de inteiros e devolve a lista
obtida da lista original em que todos os elementos pares são duplicados. Não é necessário
validar os dados de entrada. Por exemplo:
>>> duplica_elementos_pares([2, 3, 4, 5, 6, 7])
[2, 2, 3, 4, 4, 5, 6, 6, 7]

def d u p l i c a e l e m e n t o s p a r e s ( l s t ) :
nova lst = [ ]
for elem in l s t :
n o v a l s t += [ elem ]
i f elem % 2 == 0 :
n o v a l s t += [ elem ]
return n o v a l s t

Pergunta 5 (val. 1)
Escreva a função apenas digitos pares que recebe um número inteiro não negativo n, e devolve
um inteiro composto apenas pelos dı́gitos pares de n. Se n não tiver dı́gitos pares, a função
deve devolver zero. Não pode usar cadeias de caracteres. Não é necessário validar os dados
de entrada. Por exemplo:
>>> apenas_digitos_pares(664426383905433)
664426804

def a p e n a s d i g i t o s p a r e s (num ) :
novo num , b = 0 , 0
while num > 0 :
d i g = num % 10
i f d i g % 2 == 0 :
novo num += d i g ∗ 10∗∗ b
b += 1
num = num // 10
return novo num

Pergunta 6 (val. 1)
Suponha que existe predicado de um argumento eh primo, que recebe um número natural e
devolve verdadeiro apenas se o seu argumento é um número primo. Usando um ou mais dos
funcionais sobre listas (filtra, transforma, acumula), escreva a função conta primos, que recebe
uma lista de inteiros, e devolve o número de elementos da lista que são primos. A sua função
deve conter apenas uma instrução, a instrução return. Não é necessário validar os dados de
entrada. Por exemplo:

3
>>> conta_primos([1, 2, 3, 4, 5, 6])
3

def c o n t a p r i m o s ( l s t ) :
return acumula (lambda x , y : x+y , \
t r a n s f o r m a (lambda x : 1 , f i l t r a ( eh primo , l s t ) ) )

Pergunta 7 (val. 3)
Escreva a função soma digitos impares que recebe um número inteiro positivo n, e devolve
a soma de dı́gitos pares de n. As suas funções não podem usar cadeias de caracteres. Não
necessita de verificar a validade dos argumentos. Por exemplo:

>>> soma_digitos_impares(92)
9
>>> soma_digitos_impares(18126)
2

a) Usando recursão com operações adiadas (não pode utilizar a atribuição nem os ciclos while
e for).
def s o m a d i g i t o s i m p a r e s o a (num ) :
i f num==0:
return 0
e l i f num % 2 != 0 :
return num%10 + s o m a d i g i t o s i m p a r e s o a (num//10)
else :
return s o m a d i g i t o s i m p a r e s o a (num//10)
b) Usando recursão de cauda (não pode utilizar a atribuição nem os ciclos while e for).
def s o m a d i g i t o s i m p a r e s r c (num ) :
def aux (num , r e s ) :
i f num == 0 :
return r e s
e l i f num % 2 != 0 :
return aux (num/ / 1 0 , r e s + num%10)
else :
return aux (num/ / 1 0 , r e s )
return aux (num , 0 )
c) Usando um processo iterativo.
def s o m a d i g i t o s i m p a r e s i t (num ) :
soma = 0
while num > 0 :
i f num % 2 != 0 :

4
soma += num % 10
num = num // 10
return soma

Pergunta 8 (val. 2)
Escreva a função soma dicionarios que recebe dois dicionários, cujos valores associados às
chaves correspondem a listas, e devolve o dicionário que contém todas as chaves contidas em
pelo menos um dos dicionários e o valor associado a cada chave corresponde à lista obtida pela
união (no sentido de conjuntos) das listas correspondendo às chaves existentes nos dicionários.
Por exemplo:

>>> d1 = {’a’ : [1, 2], ’b’ : [3, 4]}


>>> d2 = {’b’ : [4, 5], ’c’ : [6, 7]}
>>> soma_dicionarios (d1, d2)
{’a’: [1, 2], ’b’: [3, 4, 5], ’c’: [6, 7]}

def s o m a d i c i o n a r i o s ( d1 , d2 ) :
nd = {k : d1 [ k ] [ : ] for k in d1}

for k in d2 :
i f k in nd :
for e in d2 [ k ] :
i f e not in nd [ k ] :
nd [ k]= nd [ k ] + [ e ]
else :
nd [ k ] = d2 [ k ] [ : ]

return nd

Pergunta 9 (val. 3)
Uma árvore binária é um tipo de dados que corresponde a uma estrutura hierárquica. Uma
árvore binária ou é vazia ou é constituı́da por uma raiz que domina duas árvores binárias, a
árvore esquerda e a árvore direita.
O tipo árvore binária tem as seguintes operações básicas, as quais se referem ao tipo elemento
que corresponde ao tipo dos elementos da raiz:
Construtores:

• nova arv(): tem como valor uma árvore vazia.

• cria arv(r, ae, ad), em que r é do tipo elemento e ae e ad são árvores binárias. Tem
como valor a árvore binária com raiz r, com árvore esquerda ae e com árvore direita ad.

5
Seletores:
• raiz(a), recebe uma árvore binária, a, e tem como valor a sua raiz. Se a árvore for vazia,
o valor desta função é indefinido.
• arv esq(a), recebe uma árvore binária, a, e tem como valor a sua árvore esquerda. Se a
árvore for vazia, o valor desta operação é indefinido.
• arv dir(a), recebe uma árvore binária, a, e tem como valor a sua árvore direita. Se a
árvore for vazia, o valor desta operação é indefinido.
Reconhecedores:
• eh arv(arg), recebe como argumento um elemento de um tipo qualquer e decide se este
pertence ou não ao tipo árvore binária.
• eh arv vazia(a), recebe uma árvore binária, a, e tem o valor verdadeiro se a é uma árvore
vazia e tem o valor falso, em caso contrário.
Não consideramos testes nas operações básicas.
a) Escolha uma representação para árvores binárias
R[arvore bin] = tuple(raiz, arv esq, arv dir)
b) Escreva as operações básicas em termos da sua representação
def n o v a a r v ( ) :
return ( )

def c r i a a r v ( r , ae , ad ) :
return r , ae , ad

def r a i z ( a ) :
return a [ 0 ] i f a e l s e None

def a r v e s q ( a ) :
return a [ 1 ] i f a e l s e None

def a r v d i r ( a ) :
return a [ 2 ] i f a e l s e None

def e h a r v ( ar g ) :
return type ( a rg ) == tuple and ( len ( a rg ) == 0 or \
len ( a rg ) == 3 and e h a r v ( ar g [ 1 ] ) and e h a r v ( ar g [ 2 ] ) )

def e h a r v v a z i a ( a ) :
return len ( a ) == 0
c) Escreva o predicado arv iguais que recebe duas árvores binárias e devolve verdadeiro apenas
se as árvores recebidas são iguais. Duas árvores são iguais, se forem ambas vazias ou se tiverem
a mesma raiz e as árvores esquerda e direita forem recursivamente iguais.

6
def a r v i g u a i s ( a1 , a2 ) :
i f not e h a r v ( a1 ) or not e h a r v ( a2 ) :
r a i s e Val ueErro r
i f e h a r v v a z i a ( a1 ) and e h a r v v a z i a ( a2 ) :
return True
i f e h a r v v a z i a ( a1 ) or e h a r v v a z i a ( a2 ) :
return F a l s e
i f r a i z ( a1 ) != r a i z ( a2 ) :
return F a l s e
return a r v i g u a i s ( a r v e s q ( a1 ) , a r v e s q ( a2 ) ) and \
a r v i g u a i s ( a r v d i r ( a1 ) , a r v d i r ( a2 ) )

Pergunta 10 (val. 2)
Defina a classe piscina que simula o comportamento de uma piscina pública. A piscina tem
uma lotação máxima e uma tarifa, de acordo com a seguinte regra: €2 fixo inicial mais €0.5
por cada hora ou fração, com um custo máximo de €5. Por exemplo, se uma pessoa estiver 3
horas e 20 minutos na piscina irá pagar € 4.00 (€2 iniciais, mais € 1,50 pelas primeiras 3 horas
e 0,5 pela fração seguinte). Assuma que sempre que se acede à piscina o BI da pessoa que
entra é associado à hora em que entrou (horas e minutos). Não se considera a data de entrada
pois todos os banhistas são expulso à meia noite. Sempre que se sai da piscina é indicada a
hora de saı́da e calcula-se a quantia a pagar. As instâncias desta classe são criadas indicando
a lotação máxima da piscina. Os métodos disponı́veis são os seguintes:

• entra(bi, h, m) regista que a pessoa identificada pelo seu bi como uma cadeia de carateres
entrou na piscina às h horas e m minutos. Este método verifica a legalidade das horas
e minutos de entrada e devolve o número de pessoas na piscina. Se a piscina estiver
sem lugares livres gera uma mensagem. Se uma pessoa com o mesmo BI já estiver na
piscina, gera uma mensagem e a pessoa não entra.

• sai(bi, h, m) regista que o pessoa com BI bi saiu da piscina às h horas e m minutos.
Este método verifica a legalidade das horas e minutos de saı́da, comparando-a com as
horas e minutos de entrada. Devolve o valor a pagar. Se a piscina estiver vazia gera
uma mensagem. Se o pessoa com o BI não estiver na piscina, gera uma mensagem.

• ocupacao() devolve o número de pessoas dentro da pisina.

Por exemplo:

>>> p = piscina(3)
>>> p.entra(’5555555’, 5, 12)
1
>>> p.entra(’5555555’, 12, 30)
’entra: a pessoa está na piscina’
>>> p.sai(’5555555’, 5, 10)

7
’sai: horas erradas’
>>> p.entra(’6666666’, 9, 27)
2
>>> p.entra(’7777777’, 9, 27)
3
>>> p.entra(’8888888’, 9, 27)
’entra: piscina cheia’
>>> p.ocupacao()
3
>>> p.sai(’7777777’, 10, 37)
’valor a pagar: Euro 3.0’
>>> p.sai(’5555555’, 17, 35)

class piscina :
def i n i t ( self , places ):
s e l f . places = places
s e l f . r e g = {}

def ocupacao ( s e l f ) :
return len ( s e l f . r e g )

def e n t r a ( s e l f , bi , h , m) :
i f s e l f . ocupacao ( ) == s e l f . p l a c e s :
r a i s e Val ueErro r ( ’ e n t r a : p i s c i n a c h e i a ’ )
i f b i in s e l f . r e g :
r a i s e Val ueErro r ( ’ e n t r a : a p e s s o a e s t a na p i s c i n a ’ )
i f h not in range ( 0 , 2 4) or m not in range ( 0 , 6 0 ) :
r a i s e Val ueErro r ( ’ e n t r a : h o r a s e r r a d a s ’ )
s e l f . r e g [ b i ] = h∗60+m
return s e l f . ocupacao ( )

def s a i ( s e l f , bi , h , m) :
i f s e l f . ocupacao ( ) == 0 :
r a i s e Val ueErro r ( ’ s a i : v a z i a ’ )
i f b i not in s e l f . r e g :
r a i s e Val ueErro r ( ’ s a i : a p e s s o a nao e s t a na p i s c i n a ’ )
i f h not in range ( 0 , 2 4) or m not in range ( 0 , 6 0 ) \
or (60 ∗ h+m < s e l f . r e g [ b i ] ) :
r a i s e Val ueErro r ( ’ e n t r a : h o r a s e r r a d a s ’ )
t = 60∗h+m − s e l f . r e g [ b i ]
v a l = 2 + ( t //60 + ( 1 i f t %60!=0 e l s e 0 ) ) ∗ 0 . 5
v a l = v a l i f v a l <5 e l s e 5
del s e l f . r e g [ b i ]
return ’ v a l o r a pagar : Euro {} ’ . format ( v a l i f v a l < 5 e l s e 5 . 0 )

8
Pergunta 11 (val. 1.5)
Usando palavras suas e, no máximo, em três linhas responda às seguintes questões. Respostas
dadas através de exemplos serão classificadas com zero valores.
a) Diga o que é um algoritmo e quais são as suas caracterı́sticas (sem as descrever).
Um algoritmo é uma sequência finita de instruções bem definidas e não ambı́guas
cada uma das quais pode ser executada mecanicamente num perı́odo de tempo finito
e com uma quantidade de esforço finito. Um algoritmo é rigoroso, eficaz e deve
terminar.
b) Qual a relação entre um programa e um algoritmo?
Um programa corresponde a um algoritmo escrito numa linguagem de programação.
c) Qual a relação entre um processo e um programa.
Um processo corresponde ao conjunto de ações tomadas por um computador durante
a execução de um programa.

Você também pode gostar