Estruturas lineares
Para os exercícios deste capítulo, considere definidos os tipos:
• pilha implementado como a classe pilha com os métodos pilha, empurra, topo, tira, pilha_vazia e __repr__
• fila implementado como a classe fila com os métodos fila, coloca, retira, inicio e __repr__
tal como apresentados no livro. 1. Considerando a classe pilha:
(a) (2) Defina a função verte, que recebe dois argumentos do tipo pilha: uma pilha não vazia e uma segunda pilha vazia. Esta função tem por objectivo colocar os elementos da primeira pilha na segunda pilha, por ordem inversa.
(b) (2) Defina a função inverte, que recebe como argumento uma pilha e inverte a ordem dos elementos na pilha.
2. Considerando a classe pilha:
(a) (2) Defina a classe pilha_inteiros como uma subclasse de pilha. (b) (2) Defina os métodos:
• __add__, que soma um inteiro a todos os elementos da pilha de inteiros • __sub__, que subtrai um inteiro a todos os elementos da pilha de inteiros Mostra-se a seguir um exemplo de interacção:
>>> p2 = pilha_inteiros() >>> p2.empurra(3) >>> p2.empurra(12) >>> p2 12 3 === >>> p2.empurra(12.3) 57
58 CAPÍTULO 13. ESTRUTURAS LINEARES Traceback (most recent call last):
File "C:\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 1, in <module> # Used internally for debug sandbox under external interpreter
File "C:\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 151, in empurra builtins.ValueError: pilha_inteiros: so pode inserir inteiros
>>> p2 + 3 >>> p2 15 6 === >>> p2 - 2 >>> p2 13 4 ===
3. (3) Defina a classe fila_ordenada como uma subclasse da classe fila definida no livro. Nesta classe os elementos são colocados na fila de forma ordenada. O construtor deste tipo recebe como argumento uma função de dois argumentos, que reconhece os casos em que a sequência constituída pelo primeiro e segundo argumento está de acordo com a ordem pretendida. Poderíamos ter a seguinte interacção:
>>> def maior(a,b): return a > b >>> f = fila_ordenada(maior) >>> f.coloca(2) >>> f.coloca(1) >>> f.retira() 1 >>> f.retira() 2 >>> f.fila_vazia() True
4. (3) A estrutura de informação DEQE (do Inglês “Double Ended Queue”) corresponde a uma fila à qual novos elementos podem ser adicionados a qualquer das extremidades e elementos podem ser removidos de qualquer das extremidades. Defina as operações básicas para uma DEQE e implemente a classe DEQE.
5. (2) Implemente a classe fila2, que deve ter o mesmo comportamento que a classe fila apresentada no livro, como uma subclasse de DEQE.
6. (4) Considerando a classe fila, escreva um procedimento procura_largura que, dados um elemento inicial, uma lista de procedimentos que geram os sucessores de um elemento, e um predicado que indica se já se atingiu o objectivo, executa uma procura em largura. Este procedimento deve devolver uma lista com o caminho desde a solução até ao nó inicial. Note que para devolver este caminho tem que manter internamente uma fila de
nós, em que cada nó corresponde a uma sequência de elementos desde o elemento inicial até ao último elemento gerado.
Usando esse procedimento, escreva um procedimento seq que determina o caminho para chegar a um determinado número, começando em 1, e em que os sucessores de um número são o dobro do número e o dobro mais um.
>>> seq(11) [11, 5, 2, 1] >>> seq(1000)
Árvores
Para os exercícios deste capítulo, considere definido o tipo árvore implementado como a classe arvore com os métodos arvore, raiz, arv_esq, arv_dir, arv_vazia e __repr__, tal como apresentado no livro.
1. (1) Escreva uma função soma que recebe como argumentos uma árvore de inteiros e um inteiro e devolve uma árvore de inteiros cujos elementos correspondem à soma do inteiro aos inteiros da árvore na posição correspondente. Por exemplo, se
arv = arvore(1,arvore(),arvore(2,arvore(),arvore())) >>> soma(arv,2) [ 3 [] [ 4 [] [] ] ]
2. (2) Escreva uma função arvore_para_lista que recebe como argumento uma árvore de inteiros e devolve a lista dos inteiros representados na árvore. Por exemplo,
>>> arvore_para_lista(arvore(1,arvore(),arvore(2,arvore(),arvore()))) [1,2]
3. (2) Considere uma função aplica que recebe como argumentos uma árvore, uma função f de três parâmetros e um valor e se a árvore não for vazia, devolve o resultado de aplicar f a três argumentos: a raiz da árvore; o resultado de aplica aplicado à árvore esquerda da árvore, f e ao valor; e o resultado de aplica aplicado à árvore direita da árvore, f e ao valor. Se a árvore recebida for vazia, aplica devolve o valor recebido como argumento.
(a) Escreva a função aplica.
(b) Reescreva a função arvore_para_lista do problema anterior utilizando a função aplica.
62 CAPÍTULO 14. ÁRVORES 4. (3) As árvores enfeitadas são árvores que têm alguns enfeites. Estas árvores podem ser representadas por instâncias da classe arvore_enfeitada, que é uma subclasse da classe arvore, que são árvores que têm na raíz (ou nas raízes de algumas das árvores por si dominadas) enfeites ou a cadeia de caracteres ‘vazio’. Os enfeites podem ser estrelas, bolas de várias cores (brancas, encarnadas, verdes e amarelas) e vários tamanhos (grandes, médias e pequenas), luzes de várias cores (azuis, verdes, encarnadas, amarelas) e chocolates de formas distintas (presente ou coração). Para que seja considerada uma árvore de natal, uma árvore enfeitada deve ter apenas uma estrela além de outros enfeites, e a estrela deve estar numa das folhas da árvore.
Para resolver as alíneas seguintes, considere as atribuições abaixo. vazia = arvore_enfeitada()
arv = arvore_enfeitada(bola(’amarelo’,’grande’), \
arvore_enfeitada(enfeite(’estrela’),vazia,vazia), \ vazia)
(a) Implemente a classe arvore_enfeitada, que é subclasse da classe arvore, e o método arvore_natal_p, que testa se a árvore é uma árvore de natal. Implemente também a classe enfeite, com as subclasses bola, luz e chocolate. Exemplos de enfeites são bola(’amarelo’,’grande’), luz(’branco’), chocolate(’coracao’) e enfeite(’estrela’).
(b) Escreva uma função conta_bolas_amarelas que recebe como argumento uma ár-vore enfeitada e que conta as bolas amarelas da árár-vore. Por exemplo,
>>> conta_bolas_amarelas(arv) 1
(c) Reescreva a função anterior utilizando a função aplica definida no exercício ante-rior.
(d) Escreva uma função conta_enfeites_predicado que recebe como argumento uma árvore enfeitada e um predicado e que conta os enfeites da árvore que satisfazem esse predicado. Por exemplo,
>>> conta_enfeites_predicado(arv,lambda enf: isinstance(enf,bola)) 1
(e) Reescreva a função anterior utilizando a função aplica definida no exercício ante-rior.
(f) Escreva uma função arvores_natal que recebe como argumento uma árvore de natal e devolve uma lista contendo a árvore de natal e todas as árvores de natal que são por si dominadas. Por exemplo,
>>> lista = arvores_natal(arv) >>> lista[0] == arv True >>> lista[1] == arv.arv_esq() True >>> len(lista) 2