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>