Salta ai contenuti. | Salta alla navigazione

Strumenti personali

16 giugno 2016 - laboratorio

Linguaggi e Traduttori

Prof. Marco Gavanelli

16 giugno 2016

Esercizio 1 (punti 16)

Nelle elezioni con metodo proporzionale, i seggi dovrebbero essere ripartiti in proporzione ai voti ricevuti da ogni partito. In pratica, però, non è possibile seguire esattamente la proporzione, perché il numero di seggi assegnati deve sempre essere un numero intero. Per questo motivo, si utilizza un algoritmo di ripartizione dei seggi; uno dei più usati (usato anche in Italia) è il metodo d'Hondt.

Dopo che i voti sono stati contati, vengono calcolati dei quozienti successivi per ciascun partito. Il totale dei voti per ogni partito è diviso prima per 1, poi per 2, poi per 3, ecc. Si crea quindi una tabella con ha una riga per ogni partito ed un numero potenzialmente infinito di colonne; la casella (i,j) rappresenta il numero di voti del i-esimo partito diviso per j.

Se ci sono S seggi da assegnare, essi vengono assegnati ai partiti in base agli S numeri più alti nell'intera tabella.

Ad esempio, supponiamo che 8 seggi debbano essere suddivisi fra 4 partiti, chiamati A, B, C e D. I partiti hanno ricevuto i seguenti voti:

  • partito A: 100000
  • partito B: 80000
  • partito C: 30000
  • partito D: 20000

La tabella risulta:

partito /1 /2 /3 /4 /5 /6 /7 ...
A 100000 50000 33333 25000 20000 16666 14286 ...
B 80000 40000 26666 20000 16000 13333 11428 ...
C 30000 15000 10000 7500 6000 5000 4286 ...
D 20000 10000 6666 5000 4000 3333 2857 ...

Gli 8 numeri più alti nell'intera tabella sono indicati in grassetto; i seggi assegnati sono quindi:

  • partito A: 4
  • partito B: 3
  • partito C: 1
  • partito D: 0

Si scriva un programma Haskell per calcolare l'allocazione dei seggi secondo il metodo d'Hondt. Si scriva in particolare una funzione

seggi :: Int -> [Int] -> [Int]

che, dati un numero di seggi s e una lista di voti vs fornisce una lista con il numero di seggi assegnato a ciascun partito. Si può ipotizzare che la lista vs sia ordinata in ordine decrescente.

Non è necessario che la lista di uscita contenga i valori a zero; nell'esempio precedente

*Main> seggi 8 [100000,80000,30000,20000]
[4,3,1]

Esercizio 2 (Punti 2)

Si scriva un programma Lex che all'interno di ogni parentesi aggiunge il numero di parentesi aperte. Ad esempio, dato il testo

abc(asc(ddd)(dqw)((()))

produce

abc(1asc(2ddd2)(2dqw2)(2(3(44)3)2)

 

 

 

 


 

 

 

 

Soluzione Esercizio 1

 


seggi s vs = countSeats (dHondt s vs)

countSeats :: (Eq p, Num c) => [(p,c)] -> [Int]
countSeats [] = []
countSeats xs = let partito=(fst.head) xs
    in (length (filter ((==partito).fst) xs)): countSeats (filter ((/=partito).fst) xs)

dHondt seats votes = take seats (multiMerge (zipWith (\x ys -> zip (repeat x) ys) [1..] (map f votes)))

f x = (map (x/) [1..])

multiMerge xs = foldr merge [] xs

merge [] ys = ys
merge xs [] = xs
merge ((xParty,xVotes):xs) ((yParty,yVotes):ys)
   | xVotes >= yVotes  = (xParty,xVotes):merge xs ((yParty,yVotes):ys)
   | otherwise         = (yParty,yVotes):merge ((xParty,xVotes):xs) ys

Soluzione esercizio 2

 


%{
int cont=0;
%}
%%

"("		{cont++; printf("(%d",cont);}
")"		{printf("%d)",cont); cont--;}