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.
  1. (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".
  2. (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"].


SECONDA PARTE

[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à.

[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>