University Logo

Università
di Padova

Diploma in Ingegneria Informatica
Corso di Fondamenti di Informatica 2
2 Moduli

A.A. 2001/2002

Versione 1.28 24/09/2002

Soluzione delle prove in corso d'anno


Seconda prova (prima prova di programmazione)

Soluzione Tema A (zipped) (DerivaTempo)

Soluzione Tema B (zipped) (Varia)

Soluzione Tema C (zipped) (IntegraTempo)

Soluzione Tema D (zipped) (Totalizza)


Si realizzi nel package Temi, corredando il codice di adeguati commenti, quanto sotto richiesto:

1) L’interfaccia DerivaTempo che include i seguenti 3 metodi:

2) La classe Tachim, che implementa l’interfaccia DerivaTempo, memorizzando il valore di una grandezza lineare (spazio). A questo scopo mantiene la posizione lineare corrente (con segno), misurata in km (kilometri), nell'attributo denominato posiz, l'intervallo temporale di aggiornamento, misurato in s (secondi), in quantoTemp, e la velocità calcolata nell'ultimo aggiornamento e misurata in km/s, in vel. Tutti gli attributi sono floating point in doppia precisione.

Oltre ai metodi obbligatori, la classe Tachim include:

  1. visualizzare la stringa descrittiva dell'oggetto creato nel suo stato iniziale;
  2. eseguire sull'oggetto creato un ciclo di 20 passi ciascuno dei quali include:

il metodo di collaudo non deve far riferimento agli attributi dell'istanza ma vi deve operare solo attraverso i metodi pubblici.

3) La classe Tachim2 che estende Tachim ridefinendo i metodi der, aggiorna e toString in modo che il metodo der ritorni il rapporto tra posizione assoluta e intervallo temporale complessivo (una specie di velocità media), rapporto misurato in km/s. Definire nella classe Tachim2 2 costruttori analoghi a quelli previsti in Tachim.

 

Promemoria:

Math.random() metodo statico che restituisce, in un floating point in doppia precisione, un numero casuale x con:

0 £ x < 1.0.


Si realizzi nel package Temi, corredando il codice di adeguati commenti, quanto sotto richiesto:

1) L’interfaccia Varia che include i seguenti 3 metodi:

2) La classe Livello, che implementa l’interfaccia Varia, memorizzando il valore relativo ad una quantità di liquido. A questo scopo mantiene tale quantità (positiva o nulla), misurata in hl (ettolitri), nell'attributo denominato liv, l'intervallo temporale di aggiornamento, misurato in min (minuti), in interv, e il flusso (variazione temporale di livello) calcolato nell'ultimo aggiornamento e misurato in hl/min, in varLiv. Tutti gli attributi sono floating point in singola precisione. L’implementazione di nuovo deve sollevare l’eccezione java.lang.IllegalArgumentException se il suo parametro di chiamata è negativo.

Oltre ai metodi obbligatori, la classe Livello include:

  1. visualizzare la stringa descrittiva dell'oggetto creato nel suo stato iniziale;
  2. eseguire sull'oggetto creato un ciclo di 15 passi ciascuno dei quali include:

il metodo di collaudo non deve far riferimento agli attributi dell'istanza ma vi deve operare solo attraverso i metodi pubblici.

3) La classe Livello2 che estende Livello ridefinendo i metodi variaz e nuovo in modo che il metodo variaz ritorni il rapporto tra livello e intervallo temporale complessivo (una specie di ‘flusso medio’), rapporto misurato in hl/min. Definire nella classe Livello2 2 costruttori analoghi a quelli previsti in Livello.

 

Promemoria:

Math.random() metodo statico che restituisce, in un floating point in doppia precisione, un numero casuale x con:

0 £ x < 1.0.


Si realizzi nel package Temi, corredando il codice di adeguati commenti, quanto sotto richiesto:

1) L’interfaccia IntegraTempo che include i seguenti 3 metodi:

2) La classe Spazio, che implementa l’interfaccia IntegraTempo, memorizzando un valore di velocità (istantanea). A questo scopo mantiene il campione di velocità, misurata in km/s (kilometri al secondo), nell'attributo denominato vel, inizialmente nullo, l'intervallo temporale di aggiornamento, misurato in s (secondi), in quanto, e il valore corrente dello spazio come integrale, calcolato secondo la regola sopra, e misurato in km, in posiz. Tutti gli attributi sono floating point in doppia precisione.

Oltre ai metodi obbligatori, la classe Spazio include:

  1. visualizzare la stringa descrittiva dell'oggetto creato nel suo stato iniziale;
  2. eseguire sull'oggetto creato un ciclo di 20 passi ciascuno dei quali include:

il metodo di collaudo non deve far riferimento agli attributi dell'istanza ma vi deve operare solo attraverso i metodi pubblici.

3) La classe Spazio2 che estende Spazio ridefinendo i metodi integra, setCamp e toString in modo che il parametro di chiamata di setCamp rappresenti una velocità media (complessiva) in km/s, e quindi l’integrale sia ottenuto sommando al suo valore iniziale il semplice prodotto della velocità media corrente e del tempo complessivo trascorso (somma degli intervalli temporali). Definire nella classe Spazio2 2 costruttori analoghi a quelli previsti in Spazio.

 

Promemoria:

Math.random() metodo statico che restituisce, in un floating point in doppia precisione, un numero casuale x con:

0 £ x < 1.0.


Si realizzi nel package Temi, corredando il codice di adeguati commenti, quanto sotto richiesto:

1) L’interfaccia Totalizza che include i seguenti 3 metodi:

2) La classe Flusso, che implementa l’interfaccia Totalizza, memorizzando un valore di flusso (istantaneo). A questo scopo mantiene il campione di flusso, misurato in hl/m (ettolitri al minuto), nell'attributo denominato flu, inizialmente nullo, l'intervallo temporale di aggiornamento, misurato in minuti (minuti), in tempo, e il valore corrente di un livello di riempimento come integrale, calcolato secondo la regola sopra, e misurato in hl, in liv. Tutti gli attributi sono floating point in singola precisione. L’implementazione di curVal deve garantire che il livello sia sempre positivo o nullo (un valore del parametro camp, negativo e di valore assoluto grande, può al più azzerare il livello).

Oltre ai metodi obbligatori, la classe Flusso include:

  1. visualizzare la stringa descrittiva dell'oggetto creato nel suo stato iniziale;
  2. eseguire sull'oggetto creato un ciclo di 12 passi ciascuno dei quali include:

il metodo di collaudo non deve far riferimento agli attributi dell'istanza ma vi deve operare solo attraverso i metodi pubblici.

3) La classe Flusso2 che estende Flusso ridefinendo i metodi tot, curVal in modo che il parametro di chiamata di curVal rappresenti un flusso medio (complessivo) in hl/min, e quindi l’integrale sia ottenuto sommando al suo valore iniziale il semplice prodotto del flusso medio corrente e del tempo complessivo trascorso (somma degli intervalli temporali). Definire nella classe Flusso2 2 costruttori analoghi a quelli previsti in Flusso.

 

Promemoria:

Math.random() metodo statico che restituisce, in un floating point in doppia precisione, un numero casuale x con:

0 £ x < 1.0.


Terza prova

Dato il grafo orientato rappresentato dalla seguente matrice binaria di adiacenza (gli indici dei nodi sono 0..4, l'ordine degli archi uscenti da un vertice e' quello derivato dalle righe della matrice):
   | 0  1  2  3  4
---+---------------
 0 | 0  0  1  1  1
 1 | 1  0  0  0  1
 2 | 0  0  0  0  0
 3 | 0  0  1  0  0
 4 | 0  0  1  0  0
allora un possibile ordinamento topologico e` 1 0 4 3 2
Basta disegnare i nodi dall'alto nell'ordinamento proposto e verificare che gli archi sono tutti verso il basso

Per produrre la firma digitale relativa ad un messaggio M si deve applicare la chiave privata del mittente su un'impronta di M
Vedi definizione

Data la seguente espressione regolare:
numero    [0-9]
segno     [+-]

{segno}?{numero}+("**"{segno}?{numero}{numero}?)?
un lessema NON generato dall'espressione e` -3**100
Dopo ** ci possono essere al piu` 2 cifre

Se una stringa contiene i seguenti caratteri con la corrispondente frequenza:
u   20              v   12              w   3
x   9               y   16              z   5
il nodo che, nell'albero ricavato Applicando l'algoritmo di Huffman, ha frequenza 37, ha complessivamente 6 discendenti
L'albero e' il seguente: (T5 65) [(T3 28) [(v 12) (y 16)] (T4 37) [(T2 17) [(T1 8) [(w 3) (z 5)] (x 9)] (u 20)] ]

Se si applica un'istanza ricorsiva dell'algoritmo di quick sort, nella variante in-place, alla seguente porzione dell'array da ordinare, con chiavi intere e assumendo come pivot sempre l'ultima chiave della porzione corrente: 65 80 21 56 42 5 12 31 al termine la porzione risulta riordinata come 12 5 21 31 42 80 65 56
Gli scambi effettuati sono: (65 12), (80 5), e quello finale (56 31).

Supponendo che una chiave intera k sia nel range -2000<=k<=+2000, che la funzione di codice hash f(k) mappi linearmente le chiavi nel range 0<=f(k)<=4000 e che il bucket array di una tabella hash abbia 59 elementi, usando una funzione hash di tipo a mod b, la chiave 1012 viene trasformata nel codice compresso 3
f(1012)=1012+2000=3012
3012 mod 59 = 3

Nell'interfaccia InspectableLocatorOrderedDictionary viene definito il metodo:
public Locator closestBefore (Object key) throws InvalidKeyException;
Supponendo che le chiavi (intere) inserite nel dizionario siano:
2 3 7 7 10 15 17 17 20 40 80
una chiamata al metodo passando come parametro la chiave 15 restituisce un riferimento (locatore) all'elemento nel dizionario corrispondente alla chiave 15
Ricerca la maggior chiave <= di quella fornita

Se uno heap usato come coda a priorita` ha il seguente contenuto, espresso in notazione a parentesi (i nodi all'interno dello stesso livello di parentesi sono fratelli):
3 [17 [24 [27 25] 30 [33]] 8 [9 40]]
la chiamata a removeMin() produce il nuovo contenuto 8 [17 [24 [27 25] 30] 9 [33 40]]
Dapprima il 33 (ultimo nodo) sostituisce la radice (3) e poi si effettua un down-heap dalla parte minore con i seguenti scambi: (33 8), (33 9).

Nell'implementazione in forma concatenata di un albero binario (in senso stretto) con un totale di nodi pari a 13 una chiamata ad after(v) (successore nella visita in-ordine del sottoalbero) puo` al massimo visitare 6 nodi escluso v e compreso il nodo tornato
Si pensi al caso di un albero in cui il sottoalbero destro della radice e` completamente sbilanciato a sinistra e si calcola lo after della radice
N.B. È stata accettata anche la risposta: una chiamata a first(root) (primo nodo nella visita in-ordine del sottoalbero) non puo` mai tornare la radice

Se un albero binario (in senso stretto) viene utilizzato come albero astratto dell'espressione booleana con operatori & (and, piu` prioritario di or), | (or) e ~ (not, unario):
~ (D & ((A | B) & ~ C))
una visita in preordine produce la sequenza di nodi (comprendendo i nodi senza dati indicati con nil) ~ & D & | A B ~ C nil nil
l'albero ha la seguente struttura:
~ [& [D & [| [A B] ~ [C nil]]] nil]

Insertion sort puo` avere un tempo di esecuzione O(n)
si verifica se la sequenza e` inizialmente ordinata in senso inverso

Nella rappresentazione di un albero binario mediante un array e la 'numerazione di livello', dato l'albero seguente in notazione a parentesi (^ nodo sentinella, i nodi all'interno dello stesso livello di parentesi sono fratelli):
b [c [^ e [d [^ a] ^]] f [g ^]]
il nodo che nella rappresentazione ha indice 10 e` il nodo con etichetta d
La numerazione di livello va per livelli e comincia da 1 (l'indice 0 non viene utilizzato). Nell'ordine si ha 1=b 2=c 3=f 4=^ 5=e 6=g 7=^ 8 e 9 vuoti 10=d 11=^ 12..19 vuoti 20=^ 21=a

Quarta prova (seconda prova di programmazione)

Soluzione Tema A (BiVec.java) (BiList)

Soluzione Tema B (BiVect.java) (BiLifo)

Soluzione Tema C (Vec2.java) (BiQue)

Soluzione Tema D (Vecs.java) (BiStack)


Nel package Temi sia definita la seguente interfaccia:

interface BiList {

void insert(String s);

String remove();

String removeLeft();

String removeRight();

FI2.Set.ObjectIterator iter();

int size();

}

Si implementi l'interfaccia BiList con la classe BiVec, definita nel package Temi, che utilizza come struttura di supporto un'opportuna implementazione di FI2.Linear.Vector, scelta tra quelle presenti nel package FI2.Linear (quindi da non realizzare).

Detto ne, assunto dispari, il numero di elementi allocati per il vettore di supporto, il metodo insert deve inserire un nuovo elemento, passato come parametro al metodo, alternativamente nelle posizioni k1=ë ne/2û -1 e k2=ë ne/2û +1 (ad esempio rispettivamente 3 e 5 per ne=9). Quando l'inserimento avviene in k1, preliminarmente tutti gli elementi già presenti nelle posizioni k con 1£ k£ k1 vengono spostati indietro (a sinistra nelle figure) di un posto, mentre se l'inserimento avviene in k2, preliminarmente tutti gli elementi già presenti nelle posizioni k con k2£ k£ ne-2 vengono spostati avanti (a destra nelle figure) di un posto. L'elemento in posizione ë ne/2û è sempre di tipo 'sentinella'. L'inserimento solleva una opportuna eccezione se, in uno qualsiasi dei due casi, vi è già un elemento alla corrispondente estremità (in posizione 0 nel primo caso, ne-1 nel secondo). Le figure fanno vedere l'effetto di un inserimento dell'elemento "E" dopo gli inserimenti di "A", "B", "C", "D" e con ne=9. Gli elementi sentinella sono denotati da "$".

fig. 1 prima dell'inserimento fig. 2 dopo l'inserimento

Il metodo remove estrae un singolo elemento con un effetto opposto a quello del metodo insert.(nell'esempio, tre successive chiamate a remove nella situazione della figura 2, produrrebbero la rimozione ordinatamente di "E", "D" e "C"). Dopo una sequenza di successivi remove, la posizione di inserimento è quella dell'ultima rimozione.

Il metodo removeLeft rimuove l'elemento nella parte sinistra di posizione minima, sostituendolo con una sentinella (la "A" nell'esempio di fig. 1). Il metodo removeRight rimuove invece l'elemento nella parte destra di posizione massima, sostituendolo con una sentinella (la "B" nell'esempio di fig. 1). Questi due ultimi metodi non modificano la posizione di un successivo inserimento (suggerimento: per la loro realizzazione si mantengano due indici min e max che rappresentano le posizioni degli elementi estremi delle due parti).

Ciascuno dei tre metodi di rimozione solleva una opportuna eccezione se all’atto della chiamata non ci sono elementi da rimuovere nella metà prevista; in caso di rimozione avvenuta, restituiscono invece l’elemento rimosso.

Il metodo iter restituisce un iteratore che consente di scandire la struttura di dati da sinistra a destra (da indici inferiori a superiori), restituendo uno dopo l'altro gli elementi non sentinella nell'ordine in cui compaiono nel vettore di supporto.

Il metodo size restituisce il numero di elementi effettivi (non conta le sentinelle).

Come detto, le posizioni non occupate da elementi effettivi sono occupate dal riferimento ad uno stesso oggetto sentinella: si inizializzi conformemente la struttura di dati nel costruttore base della classe, che riceve come parametro il valore ne.

Si realizzi inoltre nella classe BiVec il metodo main di collaudo che alloca un'istanza della classe e, nell’ordine:


Nel package Temi sia definita la seguente interfaccia:

interface BiLifo {

void push(String s);

String pop();

String popLeft();

String popRight();

FI2.Set.ObjectIterator visit();

int size();

}

Si implementi l'interfaccia BiLifo con la classe BiVect, definita nel package Temi, che utilizza come struttura di supporto un'opportuna implementazione di FI2.Linear.Vector, scelta tra quelle presenti nel package FI2.Linear (quindi da non realizzare).

Detto ne, assunto dispari, il numero di elementi allocati per il vettore di supporto, il metodo push deve inserire un nuovo elemento, passato come parametro al metodo, alternativamente nelle posizioni k1=0 e k2=ne-1. Quando l'inserimento avviene in k1, preliminarmente tutti gli elementi già presenti nelle posizioni k con 0£ k£ ë ne/2û -2 vengono spostati avanti (a destra nelle figure) di un posto, mentre se l'inserimento avviene in k2, preliminarmente tutti gli elementi già presenti nelle posizioni k con ë ne/2û +2£ k£ ne-1 vengono spostati indietro (a sinistra nelle figure) di un posto (ad esempio ë ne/2û -2=2 e ë ne/2û +2=6 per ne=9). L'elemento in posizione ë ne/2û è sempre di tipo 'sentinella'. L'inserimento solleva una opportuna eccezione se, in uno qualsiasi dei due casi, la corrispondente metà è piena (c'e' già un elemento dati in posizione ë ne/2û -1 nel primo caso, ë ne/2û +1 nel secondo). Le figure fanno vedere l'effetto di un inserimento dell'elemento "E" dopo gli inserimenti di "A", "B", "C", "D" e con ne=9. Gli elementi sentinella sono denotati da "$".

fig. 1 prima dell'inserimento fig. 2 dopo l'inserimento

Il metodo pop estrae un singolo elemento con un effetto opposto a quello del metodo push.(nell'esempio, tre successive chiamate a pop nella situazione della figura 2, produrrebbero la rimozione ordinatamente di "E", "D" e "C"). Dopo una sequenza di successivi pop, la posizione di inserimento è quella dell'ultima rimozione.

Il metodo popLeft rimuove l'elemento nella parte sinistra di posizione massima, sostituendolo con una sentinella (la "A" nell'esempio di fig. 1). Il metodo popRight rimuove invece l'elemento nella parte destra di posizione minima, sostituendolo con una sentinella (la "B" nell'esempio di fig. 1). Questi due ultimi metodi non modificano la posizione di un successivo inserimento (suggerimento: per la loro realizzazione si mantengano due indici min e max che rappresentano le posizioni degli elementi estremi delle due parti).

Ciascuno dei tre metodi di rimozione solleva una opportuna eccezione se all’atto della chiamata non ci sono elementi da rimuovere nella metà prevista; in caso di rimozione avvenuta, restituiscono invece l’elemento rimosso.

Il metodo visit restituisce un iteratore che consente di scandire la struttura di dati da sinistra a destra (da indici inferiori a superiori), restituendo uno dopo l'altro gli elementi non sentinella nell'ordine in cui compaiono nel vettore di supporto.

Il metodo size restituisce il numero di elementi effettivi (non conta le sentinelle).

Come detto, le posizioni non occupate da elementi effettivi sono occupate dal riferimento ad uno stesso oggetto sentinella: si inizializzi conformemente la struttura di dati nel costruttore base della classe, che riceve come parametro il valore ne.

Si realizzi inoltre nella classe BiVect il metodo main di collaudo che alloca un'istanza della classe e, nell’ordine:


Nel package Temi sia definita la seguente interfaccia:

interface BiQue {

void add(int v);

int extract();

int extractLeft();

int extractRight();

int val(int pos);

int free();

}

Si implementi l'interfaccia BiQue con la classe Vec2, definita nel package Temi, che utilizza come struttura di supporto un'opportuna implementazione di FI2.Linear.Vector, scelta tra quelle presenti nel package FI2.Linear (quindi da non realizzare).

Detto ne, assunto dispari, il numero di elementi allocati per il vettore di supporto, il metodo add deve inserire un nuovo elemento, passato come parametro al metodo, alternativamente nelle posizioni k1=ë ne/2û -1 e k2=ë ne/2û +1 (ad esempio rispettivamente 3 e 5 per ne=9). Quando l'inserimento avviene in k1, preliminarmente tutti gli elementi già presenti nelle posizioni k con 1£ k£ k1 vengono spostati indietro (a sinistra nelle figure) di un posto, mentre se l'inserimento avviene in k2, preliminarmente tutti gli elementi già presenti nelle posizioni k con k2£ k£ ne-2 vengono spostati avanti (a destra nelle figure) di un posto. L'elemento in posizione ë ne/2û è sempre di tipo 'sentinella'. L'inserimento solleva una opportuna eccezione se, in uno qualsiasi dei due casi, vi è già un elemento alla corrispondente estremità (in posizione 0 nel primo caso, ne-1 nel secondo). Le figure fanno vedere l'effetto di un inserimento dell'elemento "5" dopo gli inserimenti di "1", "2, "3", "4" e con ne=9. Gli elementi sentinella sono denotati da "$".

fig. 1 prima dell'inserimento fig. 2 dopo l'inserimento

Il metodo extract estrae un singolo elemento con un effetto opposto a quello del metodo add. (nell'esempio, tre successive chiamate extract nella situazione della figura 2, produrrebbero la rimozione ordinatamente dei valori "5", "4" e "3"). Dopo una sequenza di successivi extract, la posizione di inserimento è quella dell'ultima rimozione.

Il metodo extractLeft rimuove l'elemento nella parte sinistra di posizione minima, sostituendolo con una sentinella (l'elemento di valore "1" nell'esempio di fig. 1). Il metodo extractRight rimuove invece l'elemento nella parte destra di posizione massima, sostituendolo con una sentinella (l'elemento di valore "2" nell'esempio di fig. 1). Questi due ultimi metodi non modificano la posizione di un successivo inserimento (suggerimento: per la loro realizzazione si mantengano due indici min e max che rappresentano le posizioni degli elementi estremi delle due parti).

Ciascuno dei tre metodi di rimozione solleva una opportuna eccezione se all’atto della chiamata non ci sono elementi da rimuovere nella metà prevista; in caso di rimozione avvenuta, restituiscono invece l’elemento rimosso.

Il metodo val restituisce, senza rimuoverlo, il valore dell'elemento che, contando da sinistra, si trova nella posizione passata nel parametro pos senza contare le sentinelle: ad esempio il metodo applicato al vettore di supporto come in figura 2 con pos=3 restituisce il valore "4" e con pos=0 restituisce il valore "1". Il metodo deve sollevare una opportuna eccezione se l'elemento richiesto non esiste o il parametro è negativo.

Il metodo free restituisce il numero di locazioni libere (nel conteggio si devono escludere l'elemento sentinella centrale e gli elementi occupati da dati inseriti: per l'esempio di fig. 2 free restituirebbe 3).

Come detto, le posizioni non occupate da elementi effettivi sono occupate dal riferimento ad uno stesso oggetto sentinella: si inizializzi conformemente la struttura di dati nel costruttore base della classe, che riceve come parametro il valore ne.

Si realizzi inoltre nella classe Vec2 il metodo main di collaudo che alloca un'istanza della classe e, nell’ordine:


Nel package Temi sia definita la seguente interfaccia:

interface BiStack {

void addtop(float v);

float exttop();

float extLeft();

float extRight();

float value(int pos);

int aval();

}

Si implementi l'interfaccia BiStack con la classe Vecs, definita nel package Temi, che utilizza come struttura di supporto un'opportuna implementazione di FI2.Linear.Vector, scelta tra quelle presenti nel package FI2.Linear (quindi da non realizzare).

Detto ne, assunto dispari, il numero di elementi allocati per il vettore di supporto, il metodo addtop deve inserire un nuovo elemento, passato come parametro al metodo, alternativamente nelle posizioni k1=0 e k2=ne-1. Quando l'inserimento avviene in k1, preliminarmente tutti gli elementi già presenti nelle posizioni k con 0£ k£ ë ne/2û -2 vengono spostati avanti (a destra nelle figure) di un posto, mentre se l'inserimento avviene in k2, preliminarmente tutti gli elementi già presenti nelle posizioni k con ë ne/2û +2£ k£ ne-1 vengono spostati indietro (a sinistra nelle figure) di un posto (ad esempio ë ne/2û -2=2 e ë ne/2û +2=6 per ne=9). L'elemento in posizione ë ne/2û è sempre di tipo 'sentinella'. L'inserimento solleva una opportuna eccezione se, in uno qualsiasi dei due casi, la corrispondente metà è piena (c'e' già un elemento dati in posizione ë ne/2û -1 nel primo caso, ë ne/2û +1 nel secondo). Le figure fanno vedere l'effetto di un inserimento dell'elemento "5" dopo gli inserimenti di "1", "2", "3", "4" e con ne=9. Gli elementi sentinella sono denotati da "$".

fig. 1 prima dell'inserimento fig. 2 dopo l'inserimento

Il metodo exttop estrae un singolo elemento con un effetto opposto a quello del metodo addtop.(nell'esempio, tre successive chiamate a exttop nella situazione della figura 2, produrrebbero la rimozione ordinatamente di "5", "4" e "3"). Dopo una sequenza di successivi exttop, la posizione di inserimento è quella dell'ultima rimozione.

Il metodo extLeft rimuove l'elemento nella parte sinistra di posizione massima, sostituendolo con una sentinella (l'elemento di valore "1" nell'esempio di fig. 1). Il metodo extRight rimuove invece l'elemento nella parte destra di posizione minima, sostituendolo con una sentinella (l'elemento di valore "2" nell'esempio di fig. 1). Questi due metodi non modificano la posizione di un successivo inserimento (suggerimento: per la loro realizzazione si mantengano due indici min e max che rappresentano le posizioni degli elementi estremi delle due parti).

Ciascuno dei tre metodi di rimozione solleva una opportuna eccezione se all’atto della chiamata non ci sono elementi da rimuovere nella metà prevista; in caso di rimozione avvenuta, restituiscono invece l’elemento rimosso.

Il metodo value restituisce, senza rimuoverlo, il valore dell'elemento che, contando da sinistra, si trova nella posizione passata nel parametro pos senza contare le sentinelle: ad esempio il metodo applicato al vettore di supporto come in figura 2 con pos=3 restituisce il valore "2" e con pos=0 restituisce il valore "5". Il metodo deve sollevare una opportuna eccezione se l'elemento richiesto non esiste o il parametro è negativo.

Il metodo aval restituisce il numero di locazioni libere (nel conteggio si devono escludere l'elemento sentinella centrale e gli elementi occupati da dati inseriti: per l'esempio di fig. 2 aval restituirebbe 3).

Come detto, le posizioni non occupate da elementi effettivi sono occupate dal riferimento ad uno stesso oggetto sentinella: si inizializzi conformemente la struttura di dati nel costruttore base della classe, che riceve come parametro il valore ne.

Si realizzi inoltre nella classe Vecs il metodo main di collaudo che alloca un'istanza della classe e, nell’ordine:


Prova scritta del 15/2/2002

SelSortList.java

SortSL.java

  1. Si definisca, nel package Temi, la classe SelSortList che include un metodo statico sort. Il metodo riceve come parametri una lista workList di tipo FI2.Linear.List e un comparatore cm di tipo FI2.Util.Comparator, ed effettua un ordinamento, basato sull’algoritmo di selezione, della lista workList. A tale scopo si definisca nella classe, chiamandolo opportunamente nel metodo sort, un metodo statico privato findMin che riceve come parametro una posizione start (di tipo FI2.Set.Position): il metodo restituisce la posizione del minimo trovato nella sottosequenza della lista di lavoro (il parametro workList di sort) che parte dalla posizione start fino alla fine della lista stessa (si veda l’esempio a fondo pagina). Il metodo sort NON deve utilizzare alcuna lista di supporto aggiuntiva ma deve ricollocare gli elementi minimi via via selezionati mediante operazioni di swap all’interno della lista di lavoro. Tutti i confronti sono ottenuti applicando, agli elementi della lista, il comparatore cm passato come parametro al metodo sort.
  2. Data la seguente interfaccia, definita del package Temi:
  3. interface SortableList extends FI2.Linear.List
    {
        void sort(FI2.Util.Comparator comp);
    }
    si definisca, sempre nel package Temi, la classe SortSL che implementa SortableList ed estende la classe FI2.Linear.SLList. In particolare la classe SortSL implementa il metodo sort imposto da SortableList chiamando il metodo (statico) sort della classe SelSortList, applicato alla propria istanza di lavoro (che è anche di tipo List) e utilizzando il comparatore comp. Includere nella classe SortSL un metodo main di collaudo che legge una sequenza di interi da stdin o da un file, il cui nome viene opzionalmente fornito sulla linea di comando, inserisce i valori letti nell’ordine in un’istanza di SortSL, ne visualizza il contenuto iniziale e quello ottenuto applicandovi il metodo di ordinamento (si sfrutti, per la visualizzazione del contenuto, il metodo toString() ereditato da FI2.Linear.SLList).

    Sarà oggetto di valutazione anche l’ordine e la chiarezza, commenti compresi, con cui il programma risulta sviluppato.

    Esempio di funzionamento del metodo findMin:

    6  7  12  14  40  45  23  60  79  32  19  58  47
                  ­                       ­
                  posizione di            posizione ritornata
                  partenza (start)
    

     


Prova scritta del 9/9/2002

Studenti.java

(Anag.java)

Si consideri la seguente classe, assunta già realizzata nel package Temi:

public class Anag implements Serializable {
String cognome, nome;
int matricola, annoCorso;
public Anag (String c, String n, int m, int a) { . . . };
// costruttore base che imposta i 4 attributi
public boolean equals(Object an2) { . . . }
// confronta per eguaglianza con altra istanza di tipo Anag
public String toString() { . . . };
// genera stringa descrittiva del contenuto dell'istanza
}

Si realizzi, sempre nel package Temi, la classe Studenti che mantiene un archivio di anagrafiche di studenti, ciascuno rappresentato da un’istanza di Anag, in un’istanza della classe FI2.Dictionary.OrderedArraySeq, usata secondo la tecnica dell’adattatore.

La chiave di ordinamento nel dizionario è rappresentata dalla stringa concatenazione delle prime 3 lettere del cognome e della matricola, che è composta di 6 cifre: se il cognome ha lunghezza inferiore a 3, le lettere mancanti vengono ricavate dalle prime lettere del nome (ad esempio lo studente Bianchi Egidio matricola 112233 ha chiave "Bia112233", mentre lo studente Hu Yang matricola 345678 ha chiave "HuY345678").

In particolare, oltre al costruttore base, si realizzi nella classe Studenti i seguenti metodi:

che inserisce stud come nuovo studente nel dizionario; il metodo ritorna false se l’inserimento non è avvenuto perché uno studente con la stessa chiave di stud è già presente nel dizionario, true altrimenti

[ne consegue che nel dizionario non sono ammessi due o più elementi con la stessa chiave];

che rimuove uno studente la cui anagrafica è quella del parametro stud, se presente, tornando true; il metodo ritorna false se lo studente non è presente

(si noti che, essendo libera l’impostazione del parametro stud, nel dizionario potrebbe esserci uno studente di diversa anagrafica ma con la stessa chiave di stud: in questo caso quello studente non va rimosso dal dizionario);

che torna true se lo studente passato come parametro è presente nel dizionario, false altrimenti;

che torna una copia dell’anagrafica di uno studente se la sua chiave contiene come sottostringa il parametro pattern, se ve n’è più d’uno con questa proprietà, ne restituisce uno qualsiasi di questi, null altrimenti

(sugg: si utilizzi l’iteratore delle chiavi per una ricerca lineare sugli elementi del dizionario);

che torna un iteratore per gli elementi memorizzati nell'archivio;

che permettono rispettivamente di caricare e salvare l'intero contenuto dell'archivio dal/sul file il cui pathname è passato come parametro; si noti che la classe Anag, è serializzabile mentre non lo è la classe Studenti.

Si raccomanda di leggere con attenzione le specifiche del testo cui attenersi scrupolosamente.

Sarà oggetto di valutazione anche l’ordine e la chiarezza, commenti compresi, con cui il programma risulta sviluppato.


Prova scritta del 24/9/2002

OrdT.java
LTNode.java
ListT.java

Si definisca, nel package Temi l'interfaccia OrdT che rappresenta, in forma semplificata, un albero con figli con ordine (da sinistra a destra) e che include i seguenti metodi:

 

1.      Position root()

restituisce un posizionatore alla radice dell'albero

2.      Position parent(Position v)

restituisce un posizionatore al padre del nodo v, null se v è la radice

3.      Position child(Position v, int pos)

restituisce un posizionatore al figlio del nodo v, la cui posizione da sinistra è pari a pos (0£pos£numCh-1),

null se pos non rappresenta la posizione valida di un figlio

4.      int numCh (Position v)

restituisce il numero dei figli del nodo v

5.      Position addCh(Position v, Object elem)

aggiunge un figlio a destra dell'ultimo figlio (quello più a destra) del nodo v, associando al nodo aggiunto i dati rappresentati dal parametro elem,

6.      Object setElem(Position v, Object elem)

associa al nodo v i nuovi dati rappresentati dal parametro elem, restituendo i precedenti dati associati

 

Successivamente si implementi l'interfaccia OrdT con la classe ListT nella quale i figli di un nodo, nell'ordine in cui vengono definiti, sono rappresentati da un’istanza della classe FI2.Linear.SLList. All'atto della costruzione di un'istanza di ListT il costruttore base deve generare un albero con un solo nodo radice senza dati associati. Per questa implementazione si definisca nel package la classe di supporto LTNode, che rappresenta un generico nodo della struttura di dati e implementa l'interfaccia Position; per evitare di far implementare l'interfaccia Container a ListT, si assuma che i posizionatori LTNode puntino tutti ad un contenitore sentinella.

 

Se il tempo lo consente, si implementi nella classe ListT anche un metodo main di collaudo che utilizza un'istanza di ListT come albero con elementi stringhe, ciascuna rappresentante il nome di un directory (con eventuali figli) o di un file (senza figli). Si popoli l'albero con stringhe ordinate alfabeticamente.

 

Si raccomanda di leggere con attenzione le specifiche del testo cui attenersi scrupolosamente.

Sarà oggetto di valutazione anche l’ordine e la chiarezza, commenti compresi, con cui il programma risulta sviluppato.

 

 

 


Pagina principaleTorna alla pagina principale