Informatica (CIV) - Esercitazione su FORTRAN

Informatica (CIV)
Esercitazione su FORTRAN
Andrea Romanoni
[email protected]
Dipartimento di Elettronica, Informazione e Bioingegneria
Politecnico di Milano
3 dicembre 2013
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Esercizio istogrammi
Testo
Si vuole scrivere un programma che legge da input i dati sulle
precipitazioni di pioggia (in mm) durante i giorni di un anno, e stampa a
video le precipitazioni totali (questa volta in cm) mese per mese.
Più precisamente, il programma legge da tastiera (in ordine sparso) i dati
sulle precipitazioni piovose (in mm) dei giorni dell’anno, secondo lo
schema giorno mese mm, e calcola il totale delle precipitazioni per ogni
mese dell’anno.
In seguito, stampa a video un istogramma in cui, per ogni mese
dell’anno, viene stampato un ’*’ per ogni cm di pioggia caduto in quel
mese (per semplicità i mm vengono arrotondati al cm più vicino, per cui
se, per esempio, nel mese di gennaio sono caduti in totale 46mm di
pioggia, a video vengono stampati 5 ’*’).
La stampa dell’istogramma può essere fatta in orizzontale (con i dati del
mese di gennaio più a sinistra, e quelli del mese di dicembre più a destra),
oppure in verticale (con i dati del mese di gennaio più in alto e quelli del
mese di dicembre più in basso).
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Esercizio istogrammi
Soluzione
PROGRAM piogge
IMPLICIT NONE
#include <stdio.h>
#include <stdlib.h>
INTEGER, PARAMETER :: NumeroMesiAnno = 12
#define NUM_MESI_ANNO 12
typedef enum{true, false} boolean;
CHARACTER(LEN=NumeroMesiAnno), &
PARAMETER::InizialiNomiMesiAnno = &
"GFMAMGLASOND"
int main(int argc, char const *argv[]){
INTEGER, DIMENSION(NumeroMesiAnno) :: &
PioggeMensiliMm, PioggeMensiliCm
int piogge_mensili_mm[NUM_MESI_ANNO];
int piogge_mensili_cm[NUM_MESI_ANNO];
INTEGER :: Giorno, Mese, PioggiaMm
LOGICAL :: InputTerminato
INTEGER Indice, CmCorrente
int giorno, mese, mm_pioggia;
boolean input_terminato;
int i, cm_corrente;
char iniziali_nomi_mesi[] = "GFMAMGLASOND";
INTEGER :: NumAsterischi
CHARACTER (LEN=MaxCmMese) :: Asterischi
DO Indice = 1, NumeroMesiAnno
PioggeMensiliMm(Indice) = 0
END DO
for (i = 0; i < NUM_MESI_ANNO; ++i){
piogge_mensili_mm[i] = 0;
}
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Esercizio istogrammi
Soluzione
InputTerminato = .FALSE.
DO WHILE (.NOT. InputTerminato)
WRITE (*,*) "Inserisci Giorno Mese mm"
READ (*,*) Giorno, Mese, PioggiaMm
IF (Giorno <= 0) THEN
InputTerminato = .TRUE.
ELSE
PioggeMensiliMm(Mese) = &
PioggeMensiliMm(Mese) + PioggiaMm
END IF
END DO
!=====calcolo dei dati mensili arrotondati =====
CmCorrente = 0
DO Indice = 1, NumeroMesiAnno
PioggeMensiliCm(Indice) =
PioggeMensiliMm(Indice)/10
IF ((PioggeMensiliMm(Indice) - &
PioggeMensiliCm(Indice)*10) >= 5) THEN
input_terminato = false;
do{
printf("Inserisci Giorno, Mese, mm\n");
scanf("%d %d %d", &giorno, &mese,
&mm_pioggia));
if (giorno <= 0){
input_terminato = true;
}else{
mese = mese - 1;
piogge_mensili_mm[mese] =
piogge_mensili_mm[mese] + mm_pioggia;
}
}while(input_terminato == false);
cm_corrente = 0;
for (i = 0; i < NUM_MESI_ANNO; ++i){
piogge_mensili_cm[i] =
piogge_mensili_mm[i]/10;
if ((piogge_mensili_mm[i] piogge_mensili_cm[i] * 10) >= 5){
piogge_mensili_cm[i] =
piogge_mensili_cm[i] + 1;
}
PioggeMensiliCm(Indice)=PioggeMensiliCm(Indice)+1
END IF
IF PioggeMensiliCm(Indice) > CmCorrente THEN
CmCorrente = PioggeMensiliCm(Indice)
END IF
END DO
if (piogge_mensili_cm[i] > cm_corrente){
cm_corrente = piogge_mensili_cm[i];
}
}
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Esercizio istogrammi
Soluzione
!=====stampa dell’istogramma (orizzontale)=====
WRITE (*,*) "" !va a capo
DO WHILE (CmCorrente > 0)
Asterischi = ""
/*stampa l’istogramma (orizzontale)*/
while(cm_corrente > 0){
for (i = 0; i < NUM_MESI_ANNO; ++i){
if (piogge_mensili_cm[i] > cm_corrente){
printf(" * ");
}else{
printf("
");
}
}
cm_corrente = cm_corrente - 1;
printf("\n");
}
/*stampa le lettere corrispondenti al mese*/
for (i = 0; i < NUM_MESI_ANNO; ++i){
printf(" %c ", iniziali_nomi_mesi[i]);
}
DO Indice = 1, NumeroMesiAnno
IF (PioggeMensiliCm(Indice) <= CmCorrente) &
THEN
Asterischi(Indice:Indice) = ’*’
ELSE
Asterischi(Indice:Indice) = ’ ’
END IF
END DO
WRITE (*,*) Asterischi
CmCorrente = CmCorrente - 1
END DO
WRITE (*,*) InizialiNomiMesiAnno
END PROGRAM piogge
return 0;
}
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Sequenza periodica
Testo
Scrivere un programma che legge in ingresso una sequenza di al massimo
50 numeri interi strettamente positivi (>0), terminati dallo 0, e
determina se la sequenza è “periodica”. In altre parole, il programma
determina se c’è un valore P tale per cui i numeri si ripetono ogni P
elementi della sequenza. Il programma deve anche stampare a video il
periodo P. più piccolo.
Esempi:
La sequenza 3592359235920 è periodica di periodo 4.
La sequenza 7813912830 non è periodica.
La sequenza 38383838383838380 è periodica di periodo 2.
La sequenza 444444444444444440 è periodica di periodo 1.
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Sequenza periodica
Soluzione
PROGRAM TrovaPeriodo
IMPLICIT NONE
INTEGER, DIMENSION(50) :: seq
INTEGER :: n, p, i, n_el = 0
LOGICAL :: periodico
WRITE (*,*) "Inserisci numero ", n_el + 1
READ (*,*) n
DO WHILE (n_el < 50 .AND. n /= 0)
n_el = n_el + 1
seq(n_el) = n
WRITE (*,*) "Inserisci numero", n_el + 1
READ (*,*) n
END DO
IF (n_el == 0) THEN
WRITE (*,*) "Nessun elemento inserito"
ELSE IF (n_el <= 1) THEN
WRITE (*,*) "Un solo elemento inserito,", &
" il periodo e’ 1"
ELSE
p = 0
periodico = .FALSE.
DO WHILE (.NOT. periodico .AND. p < n_el/2)
p = p+1
IF ((n_el / p) * p == n_el) THEN
periodico = .TRUE.
i = 1
DO WHILE (periodico .AND. i <= n_el-p)
IF (seq(i) /= seq(i+p)) THEN
periodico = .FALSE.
END IF
i = i+1
END DO
END IF
END DO
IF (periodico) THEN
WRITE (*,*) "La sequenza e’ periodica ", &
"di periodo ", p
ELSE
WRITE (*,*) "La sequenza non e’ periodica"
END IF
END IF
END PROGRAM TrovaPeriodo
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Esercizio punti 3D e piani
Testo A
Scrivere un sottoprogramma che prende in ingresso una sequenza di punti
dello spazio cartesiano tridimensionale a coordinate (x,y,z) intere, ed
elimina dalla sequenza tutti quei punti che non si trovano su uno stesso
piano orizzontale (cioè parallelo al piano (x.y)) con altri punti della
sequenza.
Per esempio, data la seguente sequenza di punti: <3,-2,8>,
<-340,62,31>, <8,22,8>, <8,13,-12>, <54,-10,31>, <4,72,3>
la sequenza viene modificata nel modo seguente: <3,-2,8>,
<-340,62,31>, <8,22,8>, <54,-10,31>
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Esercizio punti 3D e piani
Soluzione A
SUBROUTINE EliminaPuntiIsolati(Sequenza, Num)
IMPLICIT NONE
TYPE (Punto), INTENT(INOUT), DIMENSION(Num) :: Sequenza
INTEGER, INTENT(INOUT) :: Num
INTEGER :: Cont1, Cont2
LOGICAL :: DaTenere
TYPE :: Punto
INTEGER :: X
INTEGER :: Y
INTEGER :: Z
END TYPE Punto
DO Cont1 1, Num
DaTenere = .FALSE.
DO Cont2 = 1, Num
IF ( (Cont2 /= Cont1 ) .AND. &
(Sequenza(Cont2)%Z == Sequenza(Cont1)%Z ) ) THEN
DaTenere = .TRUE.
END IF
END DO
IF (DaTenere .EQV. .TRUE.) THEN
Cont1 = Cont1+1
ELSE
DO Cont2 = Cont1, Num-1
Sequenza(Cont2) = Sequenza(Cont2+1)
END DO
Num = Num-1
END IF
END DO
END SUBROUTINE EliminaPuntiIsolati
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Esercizio punti 3D e piani
Testo B
Scrivere un sottoprogramma che prende in ingresso una sequenza di punti
dello spazio cartesiano tridimensionale a coordinate intere, e partiziona la
sequenza in sottoinsiemi in cui ogni sottoinsieme contiene tutti e soli i
punti su uno stesso piano orizzontale (cioè parallelo al piano (x,y)).
Il sottoprogramma, sfruttando anche il sottoprogramma definito nella
parte a), restituisce una nuova sequenza di punti contenente i punti della
sequenza originale raggruppati nei sottoinsiemi descritti sopra, esclusi
però i sottoinsiemi fatti di un solo punto. I sottoinsiemi nella sequenza
restituita possono essere in ordine qualunque.
Per esempio, data la seguente sequenza di punti: <5,-2,7>,
<-10,-92,3>, <84,2,7>, <8,10,2>, <52,-20,3>, <4,72,3> una possibile
sequenza restituita è la seguente: <5,-2,7>, <84,2,7>, <-10,-92,3>,
<52,-20,3>, <4,72,3>
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Esercizio punti 3D e piani
Soluzione B
SUBROUTINE RaggruppaPunti(SequenzaIn, NumIn, SequenzaOut, NumOut)
IMPLICIT NONE
TYPE (Punto), INTENT(INOUT), DIMENSION(NumIn) :: SequenzaIn
TYPE (Punto), INTENT(OUT), DIMENSION(NumIn) :: SequenzaOut
INTEGER, INTENT(IN) :: NumIn
INTEGER, INTENT(OUT) :: NumOut
INTEGER :: i
LOGICAL :: Ordinato
TYPE (Punto) :: temp
SequenzaOut = SequenzaIn
NumOut = NumIn
CALL EliminaPuntiIsolati(SequenzaOut, NumOut)
Ordinato = .FALSE.
DO WHILE (Ordinato .EQV. .FALSE.)
Ordinato = .TRUE.
DO i=1,NumOut-1
IF(SequenzaOut(i)%Z > SequenzaOut(i+1)%Z) THEN
Ordinato = .FALSE.
temp = SequenzaOut(i)
SequenzaOut(i) = SequenzaOut(i+1)
SequenzaOut(i+1) = temp
END IF
END DO
END DO
END SUBROUTINE RaggruppaPunti
Prefisso o Suffisso?
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Confronto tra immagini
Testo
Un’immagine è costituita da una matrice di 1024x1024 pixel. Ogni pixel è
caratterizzato dal livello di intensità luminosa: tale livello è rappresentato da un
intero. Una figura originale è costituita da una matrice di 25x25 pixel.
Si vuole scrivere un sottoprogramma che, data un’immagine e data una figura
originale, verifichi se la figura appare nell’immagine. Il sottoprogramma cerca
occorrenze della figura nell’immagine, tenendo presente le seguenti sorgenti di
variabilità:
la figura potrebbe apparire non ruotata oppure ruotata di un angolo pari
+90 gradi (cioè 90 gradi in senso antiorario), rispetto all’originale;
a causa di eventuali variazioni (uniformi) di illuminazione, la figura
potrebbe apparire nell’immagine con il livello di intensità di tutti i suoi
pixel aumentati o diminuiti di un valore costante rispetto all’originale.
Il sottoprogramma deve produrre in uscita la posizione e l’orientamento della
figura nell’immagine, nel caso in cui la figura sia presente; in caso contrario
deve produrre due coordinate negative (e un qualunque valore dell’angolo di
rotazione).
NB: Anche nel caso in cui la figura appaia più volte nell’immagine, il
sottoprogramma deve produrre in uscita una sola occorrenza della figura.
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Confronto tra immagini
Soluzione
Cominciamo a definire una funzione che confronta due immagini e
restituisce vero se sono uguali, o falso se sono differenti.
LOGICAL FUNCTION ConfrontaMatrice(DimArray, Array1, Array2)
IMPLICIT NONE
INTEGER, INTENT(IN) :: DimArray
INTEGER, DIMENSION (DimArray, DimArray), INTENT(IN) :: Array1, Array2
INTEGER :: X, Y
LOGICAL, DIMENSION (DimArray, DimArray) :: ArrayConfronti
ArrayConfronti = (Array1 == Array2)
ConfrontaMatrice = .TRUE.
DO X=1, DimArray
DO Y=1, DimArray
ConfrontaMatrice = ConfrontaMatrice .AND. ArrayConfronti(X,Y)
END DO%
END DO
END FUNCTION ConfrontaMatrice
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Confronto tra immagini
Soluzione
SUBROUTINE CercaFigura(Immagine, Figura, PosX, PosY, Angolo)
IMPLICIT NONE
INTEGER, PARAMETER :: DimImmagine = 1024
INTEGER, PARAMETER :: DimFigura = 25
INTEGER,
INTEGER,
INTEGER,
INTEGER,
DIMENSION (DimImmagine, DimImmagine), INTENT(IN) :: Immagine
DIMENSION (DimFigura, DimFigura), INTENT(IN) :: Figura
INTENT(OUT) :: PosX, PosY
INTENT(OUT) :: Angolo
INTEGER, DIMENSION (DimFigura, DimFigura) :: FiguraRuotata
INTEGER :: SpostY
INTEGER :: Offset
LOGICAL :: ConfrontaMatrice
DO SpostY = 1, DimFigura
FiguraRuotata(SpostY,:) = Figura(DimFigura:1:-1,SpostY)
END DO
Prefisso o Suffisso?
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Confronto tra immagini
Soluzione
DO PosX = 1, DimImmagine-DimFigura+1
DO PosY = 1, DimImmagine-DimFigura+1
Offset = Immagine(PosX, PosY) - Figura(1,1)
IF(ConfrontaMatrice(DimFigura, &
Immagine(PosX:PosX+DimFigura-1,PosY:PosY+DimFigura-1), &
Figura(:,:) )) THEN
Angolo = 0
RETURN
END IF
Offset = Immagine(PosX, PosY) - FiguraRuotata(1,1)
IF (ConfrontaMatrice(DimFigura, &
Immagine(PosX:PosX+DimFigura-1,PosY:PosY+DimFigura-1), &
FiguraRuotata(:,:) + Offset)) THEN
Angolo = 90
RETURN
END IF
END DO
END DO
PosX = -1
PosY = -1
END SUBROUTINE CercaFigura
Prefisso o Suffisso?
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Prefisso o Suffisso?
Testo
Scrivere un programma che legge una sequenza di al massimo 100
caratteri alfabetici, terminati da un carattere non alfabetico, e
determina se la sequenza ha un prefisso e un suffisso identici, cioè
se la sequenza ha la stessa serie di caratteri al suo inizio e alla sua
fine. Il programma NON distingue i caratteri maiuscoli da quelli
minuscoli. Il programma stampa a video la sottosequenza ripetuta
più lunga tra quelle esistenti.
Esempi: La sequenza abCmpAbc6 è iniziata e terminata dalla
stringa abc.
Nella sequenza zazdazb& non c’è una sottosequenza che inizia e
termina la stringa.
La sequenza aBcDABcdabc è iniziata e terminata dalla stringa
abcdabc.
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Nel computer i caratteri vengono rappresentati con dei numeri
detti codici ASCII. Questa è la tabella di conversione:
Esercizio istogrammi
Sequenza periodica
Punti 3D e piani
Confronto tra immagini
Prefisso o Suffisso?
Prefisso o Suffisso?
Soluzione
PROGRAM PrefissoSuffisso
IMPLICIT NONE
! salvo la lunghezza effettiva
! della stringa in lng
lng = i - 1
CHARACTER (len = 100) :: sequenza
INTEGER, PARAMETER :: offset = IACHAR(’A’) IACHAR(’a’)
INTEGER :: lng, i
LOGICAL :: trovato
WRITE (*,*) "Inserire la sequenza:"
READ (*,*) sequenza
i = 1
DO WHILE (i <= LEN_TRIM(sequenza) .AND.
(
(sequenza(i) >= ’a’ .AND.
sequenza(i) <= ’z’) .OR.
(sequenza(i) >= ’A’ .AND.
sequenza(i) <= ’Z’)
)
)
IF(sequenza(i) >= ’A’ .AND. &
sequenza(i) <= ’Z’) THEN
sequenza(i) =&
ACHAR(IACHAR(sequenza(i)) - offset)
END IF
i = i+1
END DO
&
&
&
&
trovato = .FALSE.
i = lng - 1
DO WHILE (.NOT. trovato .AND. i > 0)
IF (ALL(sequenza(1:i) ==
sequenza(lng-i+1:lng))) THEN
trovato = .TRUE.
ELSE
i = i - 1
END IF
END DO
IF (trovato .EQV. .TRUE.) THEN
WRITE (*,*) "La sequenza e’ iniziata", &
"e terminata dalla stringa ", &
sequenza(1:i)
ELSE
WRITE (*,*) "Non c’e’ sottosequenza ", &
"che inizia e termina la stringa."
END IF
END PROGRAM PrefissoSuffisso