15 febbraio 2017 - laboratorio
Linguaggi e Traduttori
Prof. Marco Gavanelli
15 febbraio 2017
Esercizio 1 (punti 14)
Diana vuole portare alla festa della scuola delle torte. La nonna le ha dato una ricetta e le ha spedito la lista degli ingredienti via email nel file di testo ricetta.txt. Gli ingredienti sono riportati uno per riga; per ciascun ingrediente, sono riportati:
- nome: stringa
- peso: (Int) quantità in grammi
Fortunatamente, Diana ha in casa tutti gli ingredienti; il suo modernissimo frigorifero le fornisce automaticamente l'elenco di tutti gli alimenti che contiene in un file di testo ingredienti.txt , in cui ciascun elemento è rappresentato come prima, cioè:
- nome: stringa
- peso: (Int) quantità in grammi
Si scriva un programma Haskell che visualizza quante torte riuscirà a fare Diana.
Ad esempio, se il file ricetta.txt contiene
Zucchero | 300 |
Burro | 100 |
Farina | 350 |
ed il file ingredienti.txt contiene
Burro | 500 |
Farina | 1000 |
Latte | 1000 |
Zucchero | 700 |
il programma dovrà visualizzare che si riescono a fare 2 torte.
Diana desidera inoltre sapere quali ingredienti (e il relativo peso) dovrà acquistare per fare una torta in più; nell'esempio sopra, dovrà acquistare 200 grammi di Zucchero e 50 di Farina per poter fare 3 torte.
Si usino (e, possibilmente, definiscano) funzioni di ordine superiore per risolvere il problema. Nel voto finale è inclusa una valutazione basata sull'utilizzo di funzioni di ordine superiore, list comprehension, lazy evaluation.
Esercizio 2 (Punti 4)
Si scriva un programma Lex che, dato un file in linguaggio C, mostra solo le parti commentate fra /*
e */
.
Si ricorda che un commento in linguaggio C inizia con /*
, può contenere un testo qualsiasi (anche su più righe) ma che non contiene la sequenza */
e termina con */
.
Ad esempio, dato il programma
#include <stdio.h> /* programma per stampare Hello World! */ main() { printf("Hello world!\n"); }
il programma Lex dovrà stampare
/* programma per stampare Hello World! */
(il fatto che vengano visualizzati i simboli /*
e */
è irrilevante).
Soluzione 1
data Ingrediente = Ingrediente{ nome :: String, peso :: Int } deriving Show; converti :: [String] -> Ingrediente converti [name,weight] = Ingrediente name (read weight) lettura fileName = do inpStr <- readFile fileName return (map (converti.words) (lines inpStr)) ricerca xs y = (head (filter (((nome y)==).nome) xs)) rapportoRicerca xs y = div (peso (ricerca xs y)) (peso y) minimo (x:xs) = foldl min x xs rapporti ricetta ingrs = map (rapportoRicerca ingrs) ricetta join rs is = map (\r -> (r,(ricerca is r))) rs diff x n = n*(peso (fst x)) - (peso (snd x)) mancanti rs is n = let j = join rs is in [Ingrediente ((nome.fst) x) (diff x n) | x <- j, (diff x n)>0] main = do ricetta <- lettura "ricetta.txt" ingredienti <- lettura "ingredienti.txt" let numTorte = minimo (rapporti ricetta ingredienti) putStr "NumeroTorte = " print numTorte let listaSpesa = mancanti ricetta ingredienti (numTorte+1) putStrLn "Lista della spesa = " print listaSpesa
Soluzione 2
COMMENTTEXT ([^\*]|"*"[^/])* COMMENT "/*"{COMMENTTEXT}"*/" %% {COMMENT} printf("%s",yytext); . ; \n ; %%