Esercizio 1. (3 punti) Fondamenti di Informatica PROVA SCRITTA 25 gennaio 2016 Data l istruzione assembler MIPS add $1,$2,$3, memorizzata all interno della memoria istruzioni della CPU, descrive la sua esecuzione sul processore RISC 4000. (NOTA: organizzare la descrizione per punti fondamentali; non è ncessario fare riferimento in modo dettagliato a connessioni circuitali della CPU). Esercizio 2. (6 punti) Sia ptr il puntatore ad una lista collegata con array ed indici. Scrivere l albero sintattico dell istruzione: position = &(ptr->buffer[*position].next); nell ambito delle dichiarazioni seguenti: struct list * ptr; int * position; Riportare anche le produzioni della grammatica C utilizzate nella verifica sintattica. Indicare infine gli eventuali side effects associati all esecuzione dell istruzione. Esercizio 3. (6 punti) Scrivere la funzione C che realizza l algoritmo di ricerca binaria in forma ricorsiva su un array di valori float. Esercizio 4. (7 punti) Scrivere la funzione C che realizza l algoritmo di fusione (merge) su una lista sequenziale. La funzione riceve in ingresso la lista e la dimensione del semivettore sinistro N1. (NOTA: per la copia del semivettore sinistro utilizzare un array). Esercizio 5. (8 punti) di questo esercizio preparare programma completo per prova orale Scrivere la funzione C che riceve in ingresso una lista L collegata con puntatori di valori float, un valore target (anch esso di tipo float), ed un intero N ed opera nel modo seguente: Cerca gli elementi uguali al target e rimuove dalla lista (liberando la memoria) il primo elemento successivo diverso dal target. Al massimo possono essere rimossi N elementi; Prima di liberare la memoria di un elemento rimosso copia il suo valore in un array V che deve essere restituito tra i parametri formali della funzione, insieme al numero di elementi count copiati in V. Scrivere anche la funzione di costo e la complessità della funzione. (Esempio: L=4.5, 1.3, 1.3, 3.2, 6.7, 1.3, 2.9, 5.8, 1.3, 7.1, 1.3, target=1.3, N=2 Lista finale L=4.5, 1.3, 1.3, 6.7, 1.3, 5.8, 1.3, 7.1, 1.3, vettore V=3.2,2.9, count=2).
Soluzione Esercizio 1. L esecuzione dell istruzione add $1,$2,$3 avviene come segue: Il registro PC della CPU contiene l indirizzo della memoria istruzioni dove è memorizzata l istruzione l istruzione in uscita dalla memoria è in ingresso alla CPU è suddivisa in 6 campi: o il campo codice operativo di 6 bit è inviato alla CU per essere decodificato. La CU genera è segnali di controllo per le altre component della CPU o I successivi 5 bit codificano il primo registro operando ($2) e sono in ingresso al banco dei registri o I successivi 5 bit codificano il secondo registro operando ($3) e sono in ingresso al banco dei registri o I successivi 5 bit codificano il registro destinazione ($1) e sono in ingresso al banco dei registry o 5 bit non sono utilizzati o I 6 bit finali codificano la funzione di somma richieta alla ALU I registri 2 e 3 del banco sono mandati in ingress alla ALU, sommati ed il risultato è scritto nel reistro 1 del banco. Esercizio 2. La lista è definita come segue: struct list int free; int first; int size; struct record * buffer; ; struct record float value; int next; ; Albero sintattico in forma compatta: position = &(ptr->buffer[*position].next); <id> = &(<id>-><id>[*<id>].<id>); <var> = &(<var>-><id>[*<var>].<id>); <var> = &(<expr>-><id>[*<expr>].<id>); <var> = &(<var>[<var>].<id>); <var> = &(<expr>[<expr>].<id>); <var> = &(<var>.<id>); <var> = &(<var>); <var> = &<var>; <var> = <expr>; <expr>; <statement> Produzioni della grammatica usate nella riduzione: <statement> ::= <expr>; <expr> ::= <var> <var>=<expr> &<var> <var> ::= <id> (<var>) *<expr>! <expr[<expr>]> <expr>-><id> <var>.<id>
Nell istruzione è presente un side effect dato dall operatore di assegnamento =. L effetto è quello di assegnare la variabile puntatore position con l indirzzo del campo next dell elemento di indice *position dell array buffer della variabile strutturata puntata da ptr. Esercizio 3. #include <float.h> typedef unsigned short int boolean; #define TRUE 1 #define FALSE 0 boolean binary_search_r(float * V, int N, float target) if ( N > 0 ) if ( isequal(v[n/2],target) ) if ( isgreater(v[n/2],target) ) return binary_search_r(v,n/2,target); return binary_search_r(&v[n/2+1],n-n/2-1,target); // confronto == tra float a meno della precisone di macchina boolean isequal( float a, float b ) float diff, max; diff = fabs(a-b); a = fabs(a); b = fabs(b); max = (a>b)? a : b; if ( diff <= FLT_EPSILON*max ) // confronto > tra float a meno della precisone di macchina boolean isgreater( float a, float b ) float diff, max; diff = fabs(a-b); a = fabs(a); b = fabs(b); max = (a>b)? a : b; if ( diff > FLT_EPSILON*max ) Esercizio 4.
struct list int head; int tail; int size; int * buffer; ; void merge_slist(struct list * ptr, int N1, int * tmp) int N, l, r; for(l=0; l<n1; l++) tmp[l] = ptr->buffer[(ptr->head+l)%ptr->size]; N = (ptr->tail-ptr->head+ptr->size)%ptr->size; l = 0; r = 0; while( l<n1 && r<n-n1 ) if( tmp[l] > ptr->buffer[(ptr->head+n1+r)%ptr->size] ) ptr->buffer[(ptr->head+l+r)%ptr->size] = tmp[l]; l++; ptr->buffer[(ptr->head+l+r)%ptr->size] = ptr->buffer[(ptr->head N1+r)%ptr->size]; r++; while( l<n1 ) ptr->buffer[(ptr->head+l+r)%ptr->size] = tmp[l]; l++; Esercizio 5. #include <stdlib.h> typedef unsigned short int boolean; #define TRUE 1 #define FALSE 0 struct list int value; struct list * next_ptr; ; boolean list_to_array(struct list ** ptrptr, float target, int N, float ** V, int * count) boolean delete_found; struct list * tmp_ptr; *V = (float *)malloc(sizeof(float)*n); if( *V==NULL ) *count = 0; while( *ptrptr!=null && *count<n ) delete_found = FALSE;
if ( isequal((*ptrptr)->value,target) ) ptrptr = &((*ptrptr)->next_ptr); while( (*ptrptr)->next_ptr!= NULL && delete_found == FALSE ) if(!isequal((*ptrptr)->value,target) ) delete_found = TRUE; ptrptr = &((*ptrptr)->next_ptr); if ( delete_found ) // remove the subsequent element which is not equal to target tmp_ptr = *ptrptr; *ptrptr = (*ptrptr)->next_ptr; (*V)[*count] = (*ptrptr)->value; (*count)++; free(tmp_ptr); Il caso peggiore si può esemplificare con il caso in cui N coincide con il numero di elementi della lista (è sufficiente N/2 perché è il numero massimo di elementi che è possibile cancellare) e gli elementi della lista sono alternativamante uno uguale ed uno diverso da target. In tal caso: list_to_array(n) = c 1 list_to_array(n-2) se N > 0 c 2 se N == 0 dove c 1 è il costo (costante) per eseguire un ciclo confrontando e cancellando un element, e list_to_array(n-2) è il costo per iterare su una list che ha dimensione ridotta di 2 (si avanza dell elemento corrente ed un element viene cancellato). La soluzione è nella forma list_to_array(n) = c 1*N + c 2 per cui C list_to_array = O(N).