Salta ai contenuti. | Salta alla navigazione

Strumenti personali

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  ;

%%