Metodologie di Programmazione a.a. 2010-2011 (canale M-Z)

Esercizi di preparazione alla prova intermedia

Indice degli esercizi

Sorgenti_JavaBancaErrori_1
TabelleBibliotecaErrori_2
Insiemi_di_anagrammiQuizErrori_3
Rettangoli_disgiuntiIngranaggiErrori_4
CoprimiTransformErrori_5
MappeGeoErrori_6
Esercizio [Sorgenti_Java]
Si vuole definire una classe che permette di calcolare informazioni statistiche circa sorgenti Java contenuti in file.
  1. Definire una classe JavaCode che gestisce un file che contiene codice Java. Il costruttore prende come parametro il pathname di un file e lo apre in lettura. Definire un metodo countClasses che ritorna il numero di occorrenze della parola chiave class nel file.

  2. Definire un metodo maxDepth della classe JavaCode che ritorna la massima profondità di nidificazione di blocchi {...}, secondo i seguenti esempi:
    maxDepth ritorna 3                 maxDepth ritorna 4
    public class A {                   class B { B() {} }
        public A() {}                  public class Test {
        private int calc() {               public static void main(String[] args) {
            while (true) {                     for (int i = 0 ; i < 5 ; i++) {
                break;                             while (true) { int k = get(); }
            }                                  }
        }                                  }   
    }                                      private int get() { return 1; }
                                       }
    
  3. Usare la classe JavaCode per scrivere un programma che legge dalla linea di comando il pathname di un file (si assume contenga codice Java) e stampa il numero di definizioni di classi presenti nel file e la massima profondità di nidificazione.

Esercizio [Banca]
Definire delle classi per la gestione (semplificata) di operazioni bancarie, rispettando le seguenti indicazioni.
  1. Definire una gerarchia di classi per la gestione di semplici operazioni bancarie: prelievo, versamento e bonifico. Definire una classe base Operazione per gestire i dati comuni a tutte le operazioni bancarie: la data dell'operazione (una stringa), il numero di conto corrente (un intero positivo) e l'importo dell'operazione (un float positivo). Definire poi le sottoclassi Prelievo, Versamento e Bonifico. La classe Prelievo deve gestire il dato che indica da dove è stato effettuato il prelievo (una stringa, ad esempio "bancomat"). La classe Versamento deve gestire il dato che indica il mezzo usato per il versamento (una stringa, ad esempio "contanti") e un dato opzionale che riporta la causale del versamento (una stringa) che essendo opzionale non deve essere inizializzata nel costruttore ma dovrà esserci un metodo setCausale per fare ciò. La classe Bonifico deve gestire il dato che indica il beneficiario del bonifico (una stringa, ad esempio le coordinate bancarie del beneficiario) e un dato opzionale per la causale del bonifico che deve essere trattato come la causale della classe Versamento. Definire un metodo getCC che ritorna il numero di conto corrente, un metodo getImporto che ritorna l'importo e un metodo stampa che stampa la descrizione dell'operazione. Rendere gli oggetti di tutte le classi immutabili eccetto che per la causale.

  2. Definire una classe Conto per gestire i dati dei conti correnti: il numero del conto (un intero positivo), l'intestatario (una stringa), il saldo (un float positivo, negativo o zero) e la lista di tutte le operazioni effettuate sul conto corrente (un array di Operazione). Il costruttore prende come parametri il numero di conto e l'intestatario. Il saldo è inizializzato a zero. Definire un metodo aggiorna che prende in input un oggetto Operazione e se rappresenta una operazione relativa al conto corrente aggiunge l'operazione alla lista e aggiorna il saldo. Definire un metodo movimenti che prende in input un intero n e stampa le descrizioni delle ultime n operazioni e il saldo.

Esercizio [Errori_1]
Il seguente codice Java contiene uno o più errori. Trovare gli errori e spiegarli. In particolare, dire per ogni errore se si verifica in compilazione o durante l'esecuzione.
public class Test {
    public static void main(String[] args) {
        if (args instanceof String) return;
        float[][] matrix = new float[5][];
        Object[] oA = matrix;
        if (oA instanceof float[]) return;
        oA = new int[10];
        Object[] oB = new int[5][4];
        oA = matrix;
        oA[0] = oB[0];
    }
}

Esercizio [Tabelle]
Definire una classe Table che permette di tradurre i dati contenuti in un file in forma tabellare.
  1. La classe Table ha un costruttore che prende in input il pathname di un file. Si assume che il file sia un file di tipo testo con il seguente formato: ogni linea contiene k stringhe separate dal carattere ';' (k è lo stesso per tutte le linee però può cambiare da file a file). Tale k è il numero di colonne del file e quindi anche della tabella. La classe ha un metodo int[] colWidths() che ritorna un array w di lunghezza pari al numero di colonne del file e tale che w[i] è la massima lunghezza delle stringhe della colonna i.

  2. La classe ha un metodo print che stampa a video il contenuto del file in forma tabellare come nel seguente esempio:
    File: temperature.txt              Risultato di print()
    Città;MIN;MAX                      FILE: temperature.txt
    Roma;2;18                          Città           |   MIN | MAX |
    L'Aquila;-12.5;9                   -------------------------------
    Reggio Calabria;5;21               Roma            |     2 |  18 |
                                       L'Aquila        | -12.5 |   9 |
                                       Reggio Calabria |     5 |  21 |
    
    La prima colonna è giustificata a sinistra e le altre sono giustificate a destra.

  3. Scrivere un programma che usa la classe Table e legge dallo standard input il pathname di un file e stampa a video il contenuto del file in forma di tabella.

Esercizio [Biblioteca]
Si vuole gestire l'archivio dei documenti (libri e DVD) di una biblioteca. Ogni documento ha una collocazione. Prima di tutto definire quindi una classe Collocazione per gestire le collocazioni e i cui oggetti devono essere immutabili. Una collocazione è determinata da una stringa che specifica il nome di un reparto della biblioteca, un numero di scaffale che identifica uno scaffale del reparto e da un numero che indica una posizione nello scaffale. Poi, definire una gerarchia di classi secondo le seguenti indicazioni.
  1. Definire una classe base Documento e poi le sottoclassi Libro, DVD_Video e DVD_Audio. Un oggetto di tipo Libro consiste in una collocazione (un oggetto di tipo Collocazione), una stringa contenente l'autore o gli autori del libro, una stringa contenente il titolo e un intero contenente il numero di pagine. Un oggetto DVD_Video consiste in una collocazione, una stringa che contiene il titolo del film, una stringa che contiene il regista o i registi e un intero che contiene la durata in minuti del film. Un oggetto DVD_Audio consiste in una collocazione, una stringa che contiene il nome della casa discografica, una stringa che contiene il titolo del DVD e per ogni brano una stringa contenente il titolo del brano. I costruttori devono inizializzare tutti i campi. Definire un metodo getColl che ritorna la collocazione del documento. Definire un metodo stampa che stampa tutte le informazioni relative al documento. Definire un metodo cercaInTitolo che prende in input una stringa str e ritorna true o false a seconda che str sia contenuta o meno nel titolo del documento.

  2. Definire un metodo statico cercaTitoli della classe Documento che prende in input un array arrD di oggetti Documento e una stringa str e ritorna in un nuovo array tutti i documenti dell'array arrD il cui titolo contiene la stringa str.

Esercizio [Errori_2]
Il seguente codice Java contiene uno o più errori. Trovare gli errori e spiegarli. In particolare, dire per ogni errore se si verifica in compilazione o durante l'esecuzione.
class Pair {
    private String key, value;
    public Pair(String k, String v) {
        key = k;
        value = v;
    }
    public String getKey() { return key; }
}

class CountPair extends Pair{
    private int count;
    public CountPair(String k, String v, int c) {
        super(k, v);
        count = c;
    }
    public int getCount() { return count; }
}

public class Test {
    public static void main(String[] args) {
        Pair[] pp = new Pair[3];
        pp[0] = new CountPair("K", "V", 1);
        pp[1] = new Pair("KK", "VV");
        System.out.println(pp.getKey()+pp.getCount());
        int count = ((CountPair)pp[1]).getCount();
        String s = pp[2].getKey();
    }
}
Exercizio [Insiemi_di_anagrammi]
Due stringhe s1 e s2 sono anagrammi l'una dell'altra se ogni carattere di s1 o di s2 occorre lo stesso numero di volte in s1 e in s2.
  1.   Definire una classe Anagrammi per rappresentare insiemi di anagrammi. Il costruttore prende in input una stringa e costruisce l'insieme composto da tale stringa. Definire un metodo aggiungi che prende in input una stringa s e se s è un anagramma delle stringhe nell'insieme ed è diversa da tutte le stringhe dell'insieme allora la aggiunge all'insieme e ritorna true, altrimenti non fa nulla e ritorna false.
     
  2.   Definire un metodo seleziona della classe Anagrammi che prende in input un array di stringhe sA e elimina dall'insieme tutte le stringhe che non appaiono nell'array sA.
Esercizio [Quiz]
Definire una piccola gerarchia di classi per rappresentare quiz di vario genere (a scelta multipla, a risposta numerica e a risposta testuale) rispettando le seguenti indicazioni.
  1. Definire una classe base Quiz e le sottoclassi QuizMulti, QuizNumber e QuizWord. La classe Quiz gestisce i dati comuni: il testo del quiz (una stringa) e il punteggio (un intero). La sottoclasse QuizMulti rappresenta quiz a scelta multipla e deve quindi gestire un array di stringhe rappresentanti le possibili scelte e la risposta corretta, un char con il seguente significato: 'A' indica la prima scelta, 'B' indica la seconda scelta, e così via. La sottoclasse QuizNumber rappresenta quiz con risposta numerica e deve gestire un array di possibili risposte corrette (un array di int). La sottoclasse QuizWord rappresenta quiz con risposta data da una parola e deve gestire un array di possibili risposte corrette (un array di stringhe). Definire un metodo getScore che ritorna il punteggio del quiz. Definire un metodo isCorrect che prende in input una stringa answer e ritorna true o false a seconda che answer sia una risposta corretta o meno. Nel caso della classe Quiz il metodo ritorna sempre false, le sottoclassi devono ridefinire il metodo. Per QuizMulti solo il primo carattere di answer va considerato. Per QuizNumber la stringa answer va interpretata come un intero (si può usare il metodo Integer.parseInt()) e la risposta è corretta solo se l'intero è presente nell'array delle risposte corrette. Per QuizWord la risposta è corretta solo se answer è uguale a una delle stringhe dell'array delle risposte corrette. Definire inoltre un metodo print che prende in input un intero n è stampa il quiz come nel seguente esempio (in questo caso n = 3, il quiz è a scelta multipla, il testo è "Come si chiama il satellite del pianeta Terra?", il punteggio è 5 e le possibili scelte sono "Giove", "Luna", "Marte", "Urano"):
    Quiz 3 (score 5)
    Come si chiama il satellite del pianeta Terra?
    A. Giove
    B. Luna
    C. Marte
    D. Urano
    
  2. Definire una classe QuizTest con un metodo statico readQuizFile che prende in input il pathname di un file contenente una batteria di quiz e ritorna in un array di oggetti Quiz i quiz letti dal file. Ogni linea del file definisce un quiz secondo il seguente formato: X#T#S#R1#R2#...#RK. X è un carattere che indica il tipo del quiz: 'M' scelta multipla, 'N' a risposta numerica e 'W' a risposta testuale. T è una stringa che definisce il testo del quiz e S è una stringa che rappresenta il punteggio. Il significato delle altre stringhe R1,..., Rk dipende dal tipo di quiz. Se X = 'M' allora R1 è un singolo carattere che rappresenta la risposta corretta e R2,..., Rk sono le scelte multiple. Se X = 'N' allora R1,..., Rk sono stringhe che rappresentano le risposte numeriche corrette. Se X = 'W' allora R1,..., Rk sono le risposte corrette.
     
  3. Definire per la classe QuizTest un metodo main che, usando il metodo readQuizFile, legge dalla linea di comando i pathname di due file: il primo contiene una batteria di quiz secondo il formato specificato al punto (b) e il secondo contiene delle risposte per tali quiz con una risposta (stringa) per linea. Poi il metodo main deve stampare per ogni quiz, il testo del quiz, la relativa risposta, l'indicazione se la risposta è corretta o meno. Infine deve stampare il punteggio totale (somma dei punteggi ottenuti in tutti i quiz). Ad esempio se i due file contengono:
    FILE DEI QUIZ:                                                       FILE DELLE RISPOSTE:
    M#Come si chiama il satellite della Terra?#4#B#Giove#Luna#Marte      C
    W#Una provincia dell'Umbria.#3#Terni#Perugia                         Terni
    N#Un numero primo tra 30 e 40.#2#31#37                               31
    
    Allora il main stampa:
    Quiz 1 (score 4)
    Come si chiama il satellite della Terra?
    A. Giove
    B. Luna
    C. Marte
    Answer: C  NOT CORRECT
    Quiz 2 (score 3)
    Una provincia dell'Umbria.
    Answer: Terni  CORRECT
    Quiz 3 (score 2)
    Un numero primo tra 30 e 40.
    Answer: 31  CORRECT
    Total score: 5
    

Esercizio [Errori_3]
Il seguente codice Java contiene uno o più errori. Trovare gli errori e spiegarli. In particolare, dire per ogni errore se si verifica in compilazione o durante l'esecuzione.
class Value {
    private Object value;
    
    public Value(Object v) { value = v; }
    
    public void setValue(String v) { value = v; }
    public Object getValue() { return value; }
}

class ValueString extends Value {
    public ValueString(String s) { super(s); }
}

public class Test {
    public static void main(String[] args) {
        Value[] val = new Value[2];
        val[0] = new Value(new Value("A"));
        val[1] = new ValueString("B");
        Value v = val[0].getValue();
        Object obj = val[0].getValue();
        String s = (String)obj;
        String ss = (String)val[1].getValue();
    }
}

Esercizio [Rettangoli_disgiunti]
Definire una classe IntRect per gestire rettangoli con lati paralleli agli assi e con coordinate intere. Ogni rettangolo è quindi determinato da quattro coordinate di tipo int x1, x2, y1 e y2 tali che (x1, y1), (x1, y2), (x2, y1) e (x2, y2) sono le coordinate dei quattro spigoli del rettangolo. Assumeremo che valga sempre x1 <= x2 e y1 <= y2. Un punto di coordinate (x, y) appartiene ad un rettangolo di coordinate (x1, x2, y1, y2) se x1 <= x <= x2 e y1 <= y <= y2.
  1. Definire, usando la classe IntRect, una classe DisjointRectSet per gestire insiemi di rettangoli (del tipo rappresentato da IntRect) a due a due disgiunti. Si osservi che due rettangoli sono disgiunti se nessuno spigolo del primo rettangolo appartiene al secondo e nessuno spigolo del secondo rettangolo appartiene al primo. Il costruttore della classe inizializza l'insieme come vuoto. Inoltre la classe deve avere due metodi add e isDisjoint. Il metodo add permette di aggiungere un rettangolo (tramite un argomento di tipo IntRect) all'insieme se è disgiunto da tutti i rettangoli dell'insieme e ritorna true, altrimenti non fa nulla e ritorna false. Il metodo isDisjoint prende come argomento un rettangolo di tipo IntRect e ritorna true o false a seconda che il rettangolo sia o meno disgiunto da tutti i rettangoli nell'insieme.

  2. Aggiungere alla classe DisjointRectSet un metodo statico create che prende in input un array di IntRect e se i rettangoli dell'array sono a due a due disgiunti ritorna un oggetto di tipo DisjointRectSet che rappresenta l'insieme dei rettagoli dell'array, altrimenti ritorna null.

  3. Definire un'altro costruttore della classe DisjointRectSet che prende in input il pathname di un file che su ogni linea contiene quattro interi separati da spazi da interpretarsi come coordinate (x1, x2, y1, y2) di un rettangolo. Se tutti i rettangoli sono disgiunti allora l'oggetto costruito rappresenta tale insieme di rettangoli, altrimenti rappresenta l'insieme vuoto.
Esercizio [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. 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".
      •   Tutte e quattro le classi devono ridefinire il metodo toString() di Object ritornando una stringa che riporta tutti i dati dell'oggetto.
  2. 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"].

Esercizio [Errori_4]
Il seguente codice Java contiene uno o più errori. Trovare gli errori e spiegarli. In particolare, dire per ogni errore se si verifica in compilazione o durante l'esecuzione.
public class Test {
    public static class SubTest extends Test {
        public SubTest(int c) { super(c); }
    }
    
    public final int count;
    
    public Test(int c) { count = c; }
    
    public SubTest[][] matrix() {
        Object[] a = new SubTest[count][];
        for (int i = 0 ; i < a.length ; i++)
            a[i] = new SubTest[i];
        return (SubTest[][])a;
    }
    
    public static void main(String[] args) {
        Object[][] oA = new SubTest(10).matrix();
        int c = ((Test)(oA[5][0])).count;
        oA[3][0] = new SubTest(5);
    }
}

Esercizio [Coprimi]
Due numeri interi positivi n e m si dicono coprimi se non hanno divisori in comune oltre a 1. Ad esempio, 8 e 9 sono coprimi ma 9 e 12 non sono coprimi.
  1. Definire una classe Coprimi per gestire insiemi di numeri interi tra loro coprimi. Il costruttore inizializza l'insieme come vuoto. La classe ha due metodi aggiungi e mcd. Il metodo aggiungi prende come argomento un intero e se questo è coprimo con tutti i numeri nell'insieme lo aggiunge all'insieme e ritorna true, altrmenti non fa nulla e ritorna false. Il metodo mcd prende come argomento un intero e ritorna il massimo comun divisore tra l'intero e gli interi dell'insieme. Ad esempio se l'insieme è {15, 14, 11} e l'argomento è 35 allora il metodo ritorna 7.

  2. Aggiungere alla classe Coprimi un metodo intersezione che prende come argomento un oggetto di tipo Coprimi e ritorna un nuovo oggetto di tipo Coprimi che contiene l'intersezione dei due insiemi.

  3. Definire un'altro costruttore della classe Coprimi che prende in input il pathname di un file che su ogni linea contiene un intero. Se tutti gli interi sono coprimi allora l'oggetto costruito rappresenta tale insieme di interi, altrimenti rappresenta l'insieme vuoto.
Esercizio [Transform]
Si vuole definire una piccola gerarchia di classi per rappresentare trasformazioni di stringhe che potrebbero risultare utili in una varietà di contesti (analisi di testi, compressione dati, ecc.).
  1. Definire una classe base Transform che gestisce l'unico dato comune a tutte le trasformazioni: la descrizione (una stringa) che deve essere immutabile. Definire un metodo per leggere la descrizione o rendere il campo pubblicamente accessibile. Gli oggetti di tipo Transform devono essere istanziabili solamente da classi nello stesso package o da sottoclassi di Transform. Definire un metodo String apply(String s) che ritorna la stringa di input s e che sarà opportunamente ridefinito dalle sottoclassi.
      •   Definire una sottoclasse Cycle per rappresentare permutazioni cicliche. Una premutazione ciclica è determinata da un array di interi C = [i0,i1,...,in-1]. Il metodo apply(s) trasforma s (di lunghezza L) così che il carattere in posizione i0%L va in posizione i1%L, quello che era in posizione i1%L va in i2%L ... e infine il carattere che era in posizione in-1%L va in i0%L. Ad esempio, se C=[1,6,0] e s="abcd" allora il metodo apply(s) ritorna "cabd". Gli oggetti di tipo Cycle devono essere immutabili. Il costruttore deve lanciare IllegalArgumentException se l'array C è null o ha lunghezza minore 2 o contiene valori minori di zero. La classe deve ridefinire il metodo equals() di Object: due oggetti di tipo Cycle sono uguali se i relativi array hanno la stessa lunghezza e sono uguali a meno di rotazioni. Ad esempio, gli array [0,3,4] e [3,4,0] sono equivalenti.
      •   Definire una sottoclasse Replace per rappresentare sostituzioni periodiche. Una sostituzione periodica è determinata da una fase f, un periodo p e due array di caratteri I e O. Il metodo apply(s) trasforma s (di lunghezza di L) nel seguente modo: per ogni i=0,1,2... tale che j = f+i*p < L, se il carattere in posizione j di s è in una qualche posizione k di I allora il carattere in posizione j è sostituito con O[k]. Ad esempio, se f=1, p=2, I=['a','b','c'], O=['A','B','C'] e s="aabbcdaa" allora apply(s) ritorna "aAbBcdaA". Gli oggetti di tipo Replace devono essere immutabili. Il costruttore deve lanciare IllegalArgumentException se f<0 o p<1 o I=null o O=null o gli array I e O hanno lunghezze differenti o I contiene caratteri ripetuti. La fase e il periodo devono essere pubblicamente accessibili. La classe deve ridefinire il metodo equals() di Object: due oggetti x e x' di tipo Replace sono uguali se hanno la fase, lo stesso periodo e i relativi array I, O e I', O' sono tali che I e I' hanno la stessa lunghezza, contengono gli stessi caratteri e le sostituzioni sono le stesse. Ad esempio, I=['a','b','c'], O=['A','B','C'] e I'=['b','a','c'], O'=['B','A','C'] sono equivalenti.
      •   Definire una sottoclasse Compound per rappresentare trasformazioni composte. Una trasformazione composta è determinata da due trasformazioni t1 e t2. Il metodo apply(s) applica ad s prima la trasformazione t1 e poi la trasformazione t2. Gli oggetti di tipo Compound devono essere immutabili. Il costruttore deve lanciare IllegalArgumentException se o t1 o t2 è null. La classe deve ridefinire il metodo equals() di Object: due oggetti di tipo Compound sono uguali se le rispettive trasformazioni componenti sono uguali.
  2. Aggiungere alla classe Compound un metodo int replaceCount(int f, int p) che ritorna il numero di trasformazioni di tipo Replace con fase f e periodo p contenute, direttamente o indirettamente, nella trasformazione composta. Ad esempio, se il metodo replaceCount(0, 1) è invocato su una trasformazione composta dalle trasformazioni R, C e R è di tipo Replace con fase 0 e periodo 1, C è composta da R', Y e R' è di tipo Replace con fase 0 e periodo 1 e Y è di tipo Cycle, allora il metodo ritorna 2.

Esercizio [Errori_5]
Il seguente codice Java contiene uno o più errori. Trovare gli errori e spiegarli. In particolare, dire per ogni errore se si verifica in compilazione o durante l'esecuzione.
public class Test {
    public static void main(String[] args) {
        long[] arrL = new long[10];
        String[] arrStr = new String[20];
        arrL[0] += 5;
        arrL[1] = arrStr[0].length();
        Object[] arrObj = new Object[20];
        arrObj[0] = arrL;
        arrObj[1] = arrStr;
        arrObj[2] = ((String[])arrObj[0])[0];
        Object[][] mObj = new Object[10][];
        mObj[0] = arrL;
        mObj[1] = arrStr;
    }
}

Esercizio [Mappe]
Definire una classe Mappa per gestire mappe altimetriche. Una mappa altimetrica è rappresentata tramite una matrice rettangolare di interi M tale che M[i][j] è l'altezza (in metri rispetto al livello del mare) del punto (i, j).
  1. Definire un costruttore che prende come argomenti due interi nr e nc e costruisce una mappa nr×nc i cui elementi sono inizializzati a zero. Definire inoltre i seguenti metodi. Un metodo set che prende come argomenti tre interi i, j e h e imposta l'altezza del punto (i, j) ad h. Un metodo max che ritorna la massima altezza della mappa. Un metodo stampa che stampa la mappa come nel seguente esempio (è una mappa 3×4):
      0   2   3   2
      0   1   2   1
     -1   0   1   0
    
  2. Definire un'altro costruttore che prende come argomento una mappa (di tipo Mappa) e costruisce una copia di tale mappa.

  3. Definire un ulteriore costruttore che prende in input il pathname di un file. Il file ha il formato seguente. La prima linea contiene due interi nr e nc, separati da spazi, che specificano la dimensione della matrice. Le nr linee successive contengono ognuna nc interi separati da spazi.

Esercizio [Geo]
Si vuole definire una piccola gerarchia di classi per rappresentare entità geografiche come fiumi, laghi e città.
  1. Definire una classe base Geo che gestisce i dati comuni: il codice (una stringa) e il nome (una stringa) dell'entità geografica. Definire metodi che ritornano il codice e il nome e un metodo che stampa tutti i dati relativa all'entità (che sarà ridefinito dalle sottoclassi). Definire una sottoclasse Fiume che gestisce il dato lunghezza del fiume in Km. Definire una sottoclasse Città che gestisce il numero di abitanti e il riferimento ad un oggetto Fiume che rappresenta l'eventuale fiume che attraversa la città (se la città non è attraversata da un fiume, il riferimento sarà null). Definire metodi che permettono di impostare il fiume e di leggerlo. Definire una sottoclasse Lago che gestisce l'elenco dei fiumi immissari e l'elenco dei fiumi emissari del lago (entrambi elenchi di oggetti di tipo Fiume). Definire un metodo che permette di aggiungere un fiume immissario all'elenco degli immissari solamente se non è già presente e ritorna true, altrimenti ritorna false. Definire un metodo analogo per aggiungere un emissario. Due entità geografiche sono considerate uguali se hanno lo stesso codice.

  2. Aggiungere alla classe Geo un metodo statico che preso in input un array G di Geo e un oggetto Fiume, ritorna in un array di Città tutte le città contenute nell'array G che sono attraversate dal fiume di input. Si ricorda che due entità geografiche sono considerate uguali se hanno lo stesso codice.

Esercizio [Figure_geometriche]
Definire una classe Punto per rappresentare punti del piano a coordinate intere. Definire una gerarchia di classi per gestire figure geometriche del piano (cerchi, rettangoli e triangoli) a coordinate intere secondo le indicazioni seguenti.
  1. Definire una classe base Figura2D e le sottoclassi Cerchio, Rettangolo e Triangolo. Ogni oggetto di tipo Cerchio è determinato da un centro di tipo Punto e un raggio (intero). Ogni oggetto Rettangolo è determinato da due punti (di tipo Punto) rappresentanti lo spigolo in alto a sinistra e quello in basso a destra (il rettangolo ha i lati paralleli agli assi). Ogni oggetto Triangolo è determinato da tre punti (i vertici del triangolo). Definire un metodo area che ritorna l'area della figura geometrica. Definire un metodo minR che ritorna un oggetto Rettangolo che è il più piccolo rettangolo che contiene la figura geometrica. Definire inoltre un metodo isIn che prende in input un punto (di tipo Punto) e ritorna true o false a seconda che il punto cada all'interno o all'esterno della figura geometrica.

  2. Definire un metodo statico maxArea della classe Figura2D che prende in input un array di Figura2D e ritorna la massima area delle figure geometriche dell'array.

  3. Definire un metodo statico minRettangolo della classe Figura2D che prende in input un array di Figura2D e ritorna un oggetto Rettangolo che è il più piccolo rettangolo che contiene tutte le figure geometriche dell'array.

Esercizio [Errori_6]
Il seguente codice Java contiene uno o più errori. Trovare gli errori e spiegarli. In particolare, dire per ogni errore se si verifica in compilazione o durante l'esecuzione.
public class Esame {
    public static void main(String[] args) {
        int[][] mat = new int[8][];
        for (int i = 0 ; i < mat.length ; i++)
            mat[i][0] = i;
        Object[] objA = mat;
        if (objA instanceof int[]) return;
        Object[][] objM;
        objM = mat;
        Object[] oF = new float[5][5];
        ((float[])oF[1])[2] = 2.8f;
        objM = (Object[][])oF;
    }
}