Metodologie di Programmazione a.a. 2010-2011
Giugno 2011
Avvertenze
Le soluzioni devono essere scritte in modo chiaro e ordinato; il codice
deve essere indentato per facilitarne la lettura. Si possono consultare libri e appunti
ma non è permesso usare computer. Il voto (in trentesimi)
sarà determinato dalla somma dei punteggi ottenuti nei vari esercizi.
Chi fa solamente la Seconda Parte: i punti degli esercizi
sono da intendersi raddoppiati.
Chi fa l'intero scritto: per raggiungere la sufficienza
deve ottenere almeno 8 punti sull'esercizio Ingranaggi e almeno 10 punti
sulla Seconda Parte.
[Ingranaggi]
Una fabbrica deve mantenere un archivio
degli ingranaggi che produce. Gli ingranaggi si suddividono in semplici
(ad es. ruote dentate, pignoni, ecc.) e composti. Definire
una gerarchia di classi, secondo le indicazioni seguenti, per gestire
detto archivio.
- (max 13 punti)
Definire una classe base
Ingranaggio per gestire i dati comuni:
il codice (una stringa) e la dimensione (altezza, larghezza e profondità in mm)
rappresentata tramite una classe nidificata statica e immutabile. Entrambi i campi devono
essere immutabili. Definire metodi per leggerli. La classe deve ridefinire
il metodo equals() di Object.
Due ingranaggi sono uguali se hanno lo stesso codice.
• Definire una sottoclasse IngrSemplice per
gestire i dati di un ingranaggio semplice: il tipo (una stringa) immutabile e
l'insieme degli ingranaggi compatibili con questo ingranaggio
(cioè, che possono funzionare assieme).
Definire un metodo per leggere il tipo. Definire un metodo isCompatibile()
che prende come parametro un ingranaggio ingr e ritorna true se
ingr è compatibile con questo ingranaggio. Definire un metodo
add() che preso come parametro un ingranaggio ingr lo aggiunge
all'insieme degli ingranaggi compatibili solo se non è già presente
e non è null.
• Definire una sottoclasse IngrComposto per
gestire i dati di un ingranaggio composto: l'elenco degli ingranaggi componenti (diretti)
(questi possono essere sia semplici che composti). Definire un metodo componentCount()
che preso come parametro un ingranaggio ingr ritorna il numero di ingranaggi
uguali a ingr che sono componenti (diretti o indiretti) di questo ingranaggio.
Ad esempio, se l'elenco di un ingranaggio di codice "C0"
consiste di ingranaggi con i codici ["S1", "S2", "S1", "C1",
"C1"]
e "C1" è un ingranaggio composto il cui elenco è
["C2", "S2"] e "C2" è un ingranaggio composto il
cui elenco è ["S1", "S2"], allora il metodo componentCount()
invocato sull'ingranaggio "C0" con input un ingranaggio di codice "S2"
ritorna 5, se l'input ha codice
"C2" ritorna 2 e se l'input ha codice "S1" ritorna 4.
Definire un metodo add() che preso come parametro un ingranaggio ingr
lo aggiunge all'elenco degli ingranaggi componenti solo se ingr non è
null e non contiene (direttamente o indirettamente) questo ingranaggio come
componente. Rispetto all'esempio precedente, il metodo add() invocato sull'ingranaggio
con codice "C2" non deve permettere l'aggiunta dell'ingranaggio
con codice "C0".
- (max 5 punti) Aggiungere alla classe
IngrComposto
un metodo getCompSemplici() che ritorna in un array tutti gli ingranaggi
semplici che sono componenti diretti o indiretti di questo ingranaggio. Rispetto all'esempio
precedente, se il metodo è invocato sull'ingranaggio di codice "C0"
ritorna un array che contiene ingranaggi con i seguenti codici ["S1",
"S2", "S1", "S1", "S2", "S2",
"S1", "S2", "S2"].
[Alberi_di_Forme] (
max 13 punti)
Si vuole definire una classe per gestire alberi di forme (ad es. rettangoli, poligoni, ecc.).
Si conviene che un tipo
T è
una forma se il
tipo stesso o
un suo supertipo S implementa la seguente interfaccia generica:
public interface Shape<S> {
//Ritorna true se questa forma è coperta
//dall'unione delle forme in c
boolean isCovered(Collection<? extends S> c);
double area(); //Ritorna l'area di questa forma
}
Definire una classe
ShapeTree per gestire alberi di forme che implementa le
seguenti funzionalità.
- Un costruttore che prende come parametro una forma
root e crea
un albero con la sola radice root.
- Un metodo
contains() che prende come parametro una forma e ritorna
true se la forma appartiene all'albero.
- Un metodo
addChild() che prende come parametri due forme par
e u e aggiunge la forma u come figlio della forma par.
Se par non è nell'albero, u è già
nell'albero o è null, lancia un'eccezione
IllegalArgumentException.
- Un metodo
area() che prende come parametro una forma r
e ritorna la somma delle aree di tutte le forme del sottoalbero di r.
Se r non è nell'albero, lancia un'eccezione
IllegalArgumentException.
- Un metodo
covered() che prende come parametri una forma r
e una Collection coll di forme
(con parametro di tipo tale da garantire la massima flessibilità)
e ritorna un insieme (di tipo Set) creato ex novo di tutte le forme
del sottoalbero di r che sono coperte dalla collezione coll.
Se r non è nell'albero, lancia un'eccezione
IllegalArgumentException.
- Un metodo
isCovered() che prende come parametri due forme r
e x e ritorna true se l'insieme delle
forme del sottoalbero di r copre la forma x.
Se r non è nell'albero, lancia un'eccezione
IllegalArgumentException.
- La classe deve implementare l'interfaccia
Iterable per iterare su
tutte le forme dell'albero. L'iteratore ritornato non deve supportare il metodo
remove().
[Errori] (
max 4 punti)
Il seguente codice Java contiene uno o più errori. Trovare gli errori, spiegarli e dire per
ognuno se si verifica in compilazione o in esecuzione.
1 import java.util.*;
2
3 interface Process<T> {
4 int process(T x);
5 }
6
7 public class Esame<T> {
8 private List<Process<T>> list = new ArrayList<Process<T>>();
9
10 boolean add(Process<T> x) {
11 for (Process<T> p : list)
12 if (p.process(x) > 3) return false;
13 list.add(x);
14 return true;
15 }
16
17 int sum(Process<Process<T>> p) {
18 int sum = 0;
19 for (Process<T> e : list)
20 sum += p.process(e);
21 return sum;
22 }
23 }
[Indici] (
max 5 punti)
Scrivere un metodo generico
InvIndex che presa come parametro una
mappa che associa a chiavi di tipo generico insiemi di indici interi (come
l'indice analitico di un libro) ritorna
una lista di insiemi che nella posizione
i contiene l'insieme
delle chiavi che hanno l'indice
i nel loro insieme associato. Se non ci
sono chiavi con quell'indice, la lista contiene
null.
Nel seguente esempio, il tipo degli elementi è
String:
Mappa di input
("Red", {1, 3}), ("Blue", {2, 3, 6}), ("Gray", {})
Lista di output
0 1 2 3 4 5 6
null, {"Red"}, {"Blue"}, {"Red", "Blue"}, null, null, {"Blue"}
Il metodo deve poter accettare mappe il cui tipo dei valori è un qualsiasi
tipo che implementa
Set<Integer>