8 minutes
09 - Compito in classe
Per completezza, si rimanda al primo post del sito per ulteriori informazioni.
Si ricorda che dello stesso esercizio possono esistere più varianti.
Esercizio 1 - isSorted
Scrivere una funzione isSorted(a), con a un array di numeri. La funzione restituisce true se l’array e' ordinato in senso strettamente crescente, e false altrimenti.
Esempi:
isSorted([-21,-2,0,4,6,210]) → true
isSorted([2,6,8,8,9,21]) → false
isSorted([2,6,8,9,10,-42]) → false
function isSorted(a) {
for (let i = 0; i < a.length - 1; i++) {
if (!(a[i] < a[i+1]))
return false;
}
return true;
}
Esercizio 2 - Deframmenta
Scrivere una funzione deframmenta(a), con a array di numeri. La funzione restituisce una copia dell’array a da cui sono state eliminate le occorrenze dei numeri quando queste non sono ripetute in sequenza (ovvero in posizioni contigue dell’array) almeno una volta. Ad esempio dato l’array a = [1,1,2,3,3,3,2,2,4] la chiamata deframmenta(a) restituisce [1,1,3,3,3,2,2], dove gli elementi in posizione 2 e 8 sono stati eliminati in quanto non ripetuti in sequenza. Esempi:
deframmenta([1,1,2,3,3,3,2,2,4]) -> [1,1,3,3,3,2,2]
deframmenta([0,0,0,0,0,1,0,1,1]) -> [0,0,0,0,0,1,1]
deframmenta([1,0]) -> []
function deframmenta(a) {
return a.filter((elem,i) => ((a[i+1] == elem) || (a[i-1] == elem)))
}
// oppure
function deframmentaClassic(a) {
let deframmented = [];
if (a[0] == a[1])
deframmented.push(a[0]);
for (let i = 1; i < a.length - 1; i++) {
if (a[i] == a[i-1] || (a[i] == a[i+1]))
deframmented.push(a[i]);
}
if (a[a.length - 1] == a[a.length - 2])
deframmented.push(a[a.length-1]);
return deframmented;
}
Esercizio 3 - Arrayfy
Si scriva una funzione arrayfy(f) che, dato come argomento una funzione f : X -> Y (con X e Y qualunque), restituisca una funzione che, dato un array A con elementi di tipo X, lo modifichi sostituendo ogni elemento x di A con il valore restituito da f(x). Esempi:
Sia a=[5,2,4]. Allora dopo arrayfy(x=>0)(a), a vale [0,0,0]
Sia a=[5,2,4]. Allora dopo arrayfy(x=>2*x)(a), a vale [10,4,8]
Sia a=“pippo”.split(""). Allora dopo arrayfy(c=>c==“p”)(a), a vale [true,false,true,true,false]
typeof arrayfy(x=>0) è “function”
function arrayfy(f) {
return function (A) {
let copy = new Array(A.length);
for (let i in A) {
copy[i] = f(A[i]);
}
return copy;
}
}
/* Soluzione proposta a lezione
In stile funzionale:
function arrayfy(f) {return (a => a.forEach((x,i)=>{a[i]=f(x)}))}
In stile procedurale:
function arrayfy(f) {return (a => {for (var i in a) a[i]=f(a[i])})}
*/
Esercizio 4 - Extend
Si scriva una funzione extend(a,b) che, dati due oggetti a e b, restituisca un nuovo oggetto che ha tutte le proprietà di a e tutte quelle di b. Se a e b hanno qualche proprietà con lo stesso nome, prevale il valore contenuto in b. Esempi:
Sia a= {nome: “pippo”, età: 35} e b={nome: “andrea”, altezza: 200}, allora:
extend(a,b) restituisce {nome: “andrea”, età: 35, altezza: 200}
extend(a,{}) restituisce {nome: “pippo”, età: 35}
extend({},{}) restituisce {}
function extend(a,b) {
let newObj = {};
for (let key in b) {
newObj[key] = b[key];
}
for (let key in a) {
newObj[key] = a[key];
}
return newObj;
}
// Soluzione proposta a lezione
function extend(a,b) { return {...a, ...b} }
Esercizio 5 - Unique - TS
Scrivere una funzione Typescript “unique(a, equals)” che utilizza generics. La funzione prende come parametro un array “a” di oggetti di tipo “T” e una funzione “equals(T,T)” che confronta due oggetti di tipo T, restituendo true se sono uguali. La funzione “unique” restituisce un nuovo array contenente tutti gli elementi unici di “a” (quindi senza duplicati), nell’ordine in cui sono in “a”. Nota: la funzione equals non va implementata, viene specificata dall’utilizzatore della funzione.
Esempio:
unique([3,5,3,2,8,5],((x,y)=>x==y)) → [3,5,2,8]
unique([0,0,0,0,0,0,0],((x,y)=>x==y)) → [ 0 ]
unique([‘hello’,‘hello’, ‘how’,‘are’,‘you’],((x,y)=>x==y)) → [ ‘hello’, ‘how’, ‘are’, ‘you’ ]
function unique<T>(a: T[], equals: (x: T, y: T) => boolean): T[] {
let res: T[] = [];
for (let i = 0; i < a.length; i++) {
for (let j = 0; j < i; j++) {
if (!res.includes(a[i]) && !res.some((elem,index) => equals(a[i],elem)))
res.push(a[i])
}
}
return res;
}
Esercizio 6 - Car - TS
Scrivere in Typescript una classe Car che rappresenta un automobile. La classe ha le seguenti proprietà:
- fuelType, rappresenta il tipo di carburante, di tipo Fuel definito dal seguente enum (che trovate anche nel REPL): enum Fuel {Diesel, Gasoline, Electric};
- fuelCapacity, di tipo numerico, rappresenta la capacità massima del serbatoio o batteria; consumption, di tipo numerico, rappresenta il consumo medio, in unità di carburante per km;
- fuelLevel, di tipo numerico, rappresenta il livello del carburante rimanente nel serbatoio, o il livello della batteria. Prende valori tra 0 e fuelCapacity.
La classe contiene un costruttore che prende come parametri, nell’ordine: fuelType, fuelCapacity, consumption e fuelLevel. I primi tre parametri sono obbligatori, invece fuelLevel può mancare e ha 0 come valore di default. La classe implementa anche i seguenti metodi (usate ESATTAMENTE i nomi indicati):
- refillFuel(f) - prende come parametro una quantità di carburante/energia f e aggiorna la proprietà fuelLevel, incrementandola del valore f; attenzione a rispettare la capacità massima del serbatoio/batteria (specificata dalla proprietà fuelCapacity): se la capacità è superata, fuelLevel viene settato a fuelCapacity. Il parametro f è opzionale: se non viene specificato il metodo fa il ‘pieno’, portando il valore di fuelLevel al valore massimo possibile (cioè alla capacità massima). Il metodo restituisce il nuovo livello di carburante/energia.
- drive (km) - prende come parametro il numero di km da percorrere, e aggiorna fuelLevel considerando il consumo medio; la funzione restituisce il nuovo valore di fuelLevel. Se il livello di carburante non è sufficiente per completare il viaggio, si lancia un’eccezione di tipo NoFuelException. In caso di eccezione il livello del carburante non viene modificato.
Esempio:
let c1=new Car(Fuel.Diesel,30,0.5) -> Car { fuelType: 0, fuelCapacity: 30, consumption: 0.5, fuelLevel: 0 }
c1.drive(10) → lancia eccezione NoFuelException();
c1.refillFuel(20); → 20
c1.drive(10); → 15
c1.drive(30); → 0
c1.refillFuel(); → 30
class NoFuelException extends Error {
;
}
enum Fuel { Diesel, Gasoline, Electric }
class Car {
fuelType: Fuel;
fuelCapacity: number;
consumption: number;
fuelLevel: number;
constructor(fuelType: Fuel, fuelCapacity: number, consumption: number, fuelLevel: number = 0) {
this.fuelType = fuelType;
this.fuelCapacity = fuelCapacity;
this.consumption = consumption;
this.fuelLevel = fuelLevel;
}
refillFuel(f?: number) {
if (f === undefined) {
this.fuelLevel = this.fuelCapacity;
return this.fuelLevel;
}
if (this.fuelLevel + f > this.fuelCapacity) {
this.fuelLevel = this.fuelCapacity;
return this.fuelLevel;
}
this.fuelLevel += f;
return this.fuelLevel;
}
drive(km: number) {
if (this.consumption * km > this.fuelLevel)
throw new NoFuelException("Carburante non sufficiente per l'itenerario.")
this.fuelLevel -= this.consumption * km;
return this.fuelLevel;
}
}
Esercizio 7 - Angolo
Si scriva una funzione angolo(d) che, ricevuto come argomento un oggetto della classe Date di JavaScript, restituisca l’angolo formato dalla lancetta delle ore e quella dei minuti di un tradizionale orologio analogico (con quadrante di 12 ore). Le lancette formano due angoli: si restituisca il più piccolo, espresso come un numero positivo di gradi sessagesimali, e approssimato all’intero più vicino. Si assuma che le lancette cambino posizione in maniera continua, ogni minuto. Esempi: angolo(new Date(“2021-04-23 14:00:00”)) → 60 angolo(new Date(“2021-04-23 14:15:15”)) → 23 angolo(new Date(“2021-04-23 6:50:50”)) → 95
function angolo(d) {
let h=d.getHours()%12
let m=d.getMinutes()
let ah=(h*60+m)/(12*60)*360
let am=(m)/(60)*360
let theta = Math.abs(ah-am)
return Math.round(Math.min(theta,360-theta))
}
Esercizio 8 - Produci
Si consideri un oggetto G che rappresenta una grammatica. Le proprietà di G hanno chiavi il cui nome consiste di una sola lettera maiuscola (A-Z); il valore di queste proprietà è una stringa qualunque.
Si scriva una funzione produci(G,s) che, data una grammatica G e una stringa qualunque s, restituisca la stringa ottenuta sostituendo ogni lettera maiuscola L contenuta in s con la corrispondente stringa associata a L in G, se esiste. Tutti i caratteri che non sono chiavi di G vengono lasciati intatti.
Si scriva poi una funzione multip(G,s,k) che ripete il processo di produci k volte (con k intero non negativo), espandendo ripetutamente la stringa prodotta.
Esempio: Sia G= {A:“aAB”, B:“bb”, C:“33”}, allora:
produci(G,“CAz”) → “33aABz”
produci(G,“BAH!") → “bbaABH!”
multip(G,“CAz”,3) → “33aaaABbbbbz”
function produci(G,s) {
let newStr = "";
for (let L of s) {
if (L in G)
newStr += G[L];
else
newStr += L;
}
return newStr;
}
function multip(G,s,k) {
let newStr = produci(G,s);
for (let i = 1; i < k; i++) {
newStr = produci(G,newStr);
}
return newStr;
}
// Soluzione proposta a lezione:
function produci(G,s) {
var a=s.split("")
return a.map(c => (c in G ? G[c]:c)).join("")
}
function multip(G,s,k) {
if (k==0) return s
else return multip(G,produci(G,s),k-1)
}
Esercizio 9 - Contali
Si scriva una funzione contali(C) che, ricevuto come argomento una classe C, restituisca una classe C2 identica a C ma con in più la capacità di contare quante istanze di oggetti della classe sono stati creati. In particolare, C2 deve esporre una proprietà statica di sola lettura quanti, il cui valore sia il numero totale di istanze create fino a quel momento.
Esempio:
var A2 = contali(Array)
var S2 = contali(String)
var a=new A2() // creo un primo “Array contato”
var b=new A2(4,7,21) // creo e inizializzo un secondo “Array contato”
b.push(42) // le istanze di A2 sono Array
var c=new S2(“pippo”) // creo e inizializzo 1 “Stringa contata”
console.log(c.length) // le istanze di S2 sono String
console.log(A2.quanti) // stampa 2
console.log(S2.quanti) // stampa 1
A2.quanti=0 // ignorato
console.log(A2.quanti) // stampa ancora 2
console.log(a instanceof Array) // stampa true
// Soluzione proposta a lezione
function contali(C) {
var istanze=0
return class {
constructor(...args) {
istanze++
return new C(...args)
}
static get quanti() { return istanze}
}
}