Metodologie di Programmazione a.a. 2010-2011 (canale M-Z)
Esercizi di preparazione alla prova intermedia
Si vuole definire una classe che permette di calcolare informazioni statistiche circa
sorgenti Java contenuti in file.
-
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.
-
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; }
}
-
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.
Definire delle classi per la gestione (semplificata) di operazioni bancarie,
rispettando le seguenti indicazioni.
-
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.
-
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.
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];
}
}
Definire una classe
Table
che permette di tradurre i dati contenuti in un file
in forma tabellare.
-
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
.
-
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.
-
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.
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.
-
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.
-
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
.
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();
}
}
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
.
-
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
.
-
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
.
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.
-
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
-
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.
-
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
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();
}
}
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
.
-
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.
-
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
.
-
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.
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.
-
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.
-
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"]
.
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);
}
}
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.
-
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
.
-
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.
-
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.
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.).
-
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.
-
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.
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;
}
}
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)
.
-
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
-
Definire un'altro costruttore che prende come argomento una mappa (di tipo
Mappa
)
e costruisce una copia di tale mappa.
-
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.
Si vuole definire una piccola gerarchia di classi per rappresentare entità geografiche
come fiumi, laghi e città.
-
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.
-
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.
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.
-
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.
-
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.
-
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.
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;
}
}