20 dicembre 2017 - laboratorio
Linguaggi e Traduttori
Prof. Marco Gavanelli
20 dicembre 2017
Esercizio 1 (punti 17)
La polizia ha scoperto che la banda della Mirandola sta per effettuare un nuovo crimine. L'investigatore capo è riuscito ad intercettare un messaggio che il capo della banda, detto `Pico', ha mandato agli altri membri. Il messaggio, però, è incomprensibile: sembra costituito solo da un elenco di coppie di numeri interi. Il messaggio è riportato in un file messaggio.txt .
Uno degli investigatori, studiando il profilo del capo della banda, ha scoperto che è un grande estimatore della Divina Commedia. Forse i numeri rappresentano posizioni di parole all'interno della Divina Commedia: il primo intero potrebbe essere il numero del Canto e il secondo il numero della parola! Ad esempio, poiché il canto primo della Commedia comincia con "Nel mezzo del cammin di nostra vita", la coppia 1 2 rappresenterebbe la parola "mezzo" e 1 6 rappresenterebbe la parola "nostra".
L'investigatore ha trovato in rete il testo dell'Inferno (il primo libro della Commedia): è riportato un file commedia.txt .
Si scriva un programma Haskell che decodifica il messaggio.
Si usino opportunamente funzioni di ordine superiore. Per ottenere il massimo dei punti, si definisca almeno una funzione di ordine superiore (e la si usi).
Esercizio 2 (punti 3)
Il file databasePettine01.asp contiene un programma Prolog costituito da:
- dei termini "real(N).", dove N è un numero intero
- dei termini "lambda(A,B,C,D).", dove A, B, C e D sono numeri interi.
Si desidera convertire il file in formato Comma Separated Values (CSV), come segue:
- si vogliono eliminare tutti i termini "real(N)."
- i termini "lambda(A,B,C,D)." devono essere convertiti in una riga
A,B,C,D
seguita dal carattere a capo '\n'
Si scriva un programma Lex che, avendo in input il file databasePettine01.asp , fornisce su standard output il file in formato CSV.
Invocando quindi il programma con
converti <databasePettine01.asp >database.csv
si otterrà un file che può essere letto da un comune software per spreadsheet.
Soluzione 1
data Parola = Parola {canto::Int, pos::Int, parola::String} deriving (Show)
data Msg = Msg {cant::Int, po::Int} deriving (Show)
main = do
messaggioStr <- readFile "messaggio.txt"
let messaggio = map (letturaMessaggio.words) (lines messaggioStr)
infernoStr <- readFile "commedia.txt"
let inferno = words infernoStr
canti = map tail (filter (/=[]) (splitOn (/="CANTO") inferno))
print (map (decodif canti) messaggio)
letturaMessaggio [c,p] = Msg (read c) (read p)
decodif canti (Msg c p) = (canti!!(c-1))!!(p-1)
decodifica inferno (Msg c p) =
head (filter (\par -> (c== (canto par)) && (p==(pos par))) inferno)
splitOn f [] = []
splitOn f (x:xs) =
let ys = splitOn f xs
in if ys==[]
then if (f x)
then [[x]]
else []
else if (f x)
then (x:(head ys)):(tail ys)
else []:ys
Soluzione 2
REAL real\([0-9]*\)\. LAMBDA lambda\( EOL \)\. %% {REAL} printf(""); {LAMBDA} printf(""); {EOL} printf("\n"); %%