- Funzione per generare N numeri random uniformi interi
(l'estensione a float è banale):
(Nota: usa random_lib.c, definita a suo tempo, tanto per fare un ripassino...)
- Funzione per 'mischiare' gli elementi di un vettore di interi
(l'estensione a float è banale):
(Vale la stessa nota.)
- Passare a una function una struttura in un argomento
è più o meno equivalente a passare una normale variabile:
se ne passa una copia e quindi quello che si fa su di essa
all'interno della function non ha influenza sulla struttura
della function chiamante:
Diverso è invece il caso se si passa il puntatore alla struttura:
Ma ovviamente si può anche passare l'intero vettore di strutture
(equivalente a passare un vettore di interi o di float o altro)
e la cosa funziona:
Problemi del lunedì
- Ritorniamo alle figure relative
al calcolo delle aree mediante campionamento di punti
in un rettangolo
(vedi qui e
qui). Da
esse ci possiamo ispirare per affrontare un problema che
apparente ha poco a che fare con il precedente e sul quale torneremo
a lezione.
Per cominciare:
- per le due funzioni che abbiamo visto (circonferenza del quarto
di cerchio e 'funzione strana') si faccia l'istogramma
dei valori delle ordinate
dei soli punti rossi
(ovvero quelli sotto la curva), aumentando
eventualmente il numero totale di punti al fine da avere
meno fluttuazioni fra 'cellette' vicine dell'istogramma;
- si provi anche con altre semplici funzioni, come ad
esempio f(x)=x e f(x)=x2, con x nell'intervallo
[0,1].
Ci poniamo quindi le seguenti domande:
- che relazione c'è fra la frequenza di punti in ciascuna
celletta dell'istogramma e i valori di f(x)?
- si immaginiamo poi all'estrazione a caso di un altro punto
nel rettangolo in cui sono stati estratti gli altri;
nell'ipotesi sia 'rosso', ovvero 'sotto' la curva
definita da f(x),
in quale celletta dobbiamo credere che andrà più facilmente a finire?
- Esempio di soluzione iterativa. Un classico problemino
di Fisica elementare è quello del sasso che viene lasciato cadere
in un pozzo, si sente il tonfo nell'acqua e, cronometrando
il tempo intercorso dall'istante in cui il sasso comincia a cadere
a quando si sente il rumore, ci cerca di valutare la
profondità del pozzo (ovviamente si assuma che l'orecchio del
cronometrista sia molto vicino al punto dal quale è partito
il sasso).
Immaginiamo di aver misurato 3 s e assumiamo
340 m/s per la velocità del suono.
La soluzione classica passa per la soluzione di una equazione
di secondo grado della quale si sceglie la
'soluzione ragiovevole'.(*)
La soluzione iterativa consiste nel seguente algoritmo,
da implementare in C o in R (o in entrambi):
- si calcoli la profondità trascurando il ritardo dovuto alla
velocità finita del suono;
- da questo valore di profondità si calcoli il
tempo impiegato dal suono ad arrivare dal fondo
del pozzo al nostro orecchio;
- si sottragga questo tempo ai 3 secondi iniziali;
- si valuti nuovamente la profondità con
il nuovo valore di tempo;
- si continui finché la differenza fra valutazioni successive
della profondità non diventi "molto piccola".
(Se si è scritto il programma in R si grafichi pure
l'andamento della profondità in funzione del numero di iterazione).
[ (*) Curiosità sulla soluzione 'standard':
di quale problema
è soluzione la soluzione spuria?]
- Cammino casuale (e non solo).
Si immagini un punto che possa assumere posizioni discrete
identificate dei numeri intere e che all'istante iniziale si trovi
nella posizione indicata da 0.
- Si lancia una 'moneta'
(virtuale, da implementare con un generatore di numeri casuali),
quindi: se essa essa dà Testa si avanza verso destra (e si finisce
nella posizione '+1'), se invece dà Croce si avanza verso sinistra
(e si finisce in '-1');
- si eseguono n passi, lanciando n volte la 'moneta'
e si segna (ovvero si inserisce in un vettore)
la posizione di arrivo;
- ci si 'segna' su un altro vettore anche
il numero di volte in cui è uscito Testa;
- si ricomincia da capo, riposizionando il punto in 0
e si ripete la sequenza di n mosse per N volte.
- Infine si visualizzano graficamente i risultati.
In pratica (in R)
- per la moneta si usi (ad esempio) round(runif(1)):
- 1 → Testa → destra;
- 0 → Croce → sinistra;
- si cominci con n=10 e N=10000
(è poi interessare provare con n=9);
- per contare il numero di volte in cui si è
finiti dopo n mosse in ciascuna delle 2n+1 possibili posizioni
si usi table();
- idem per contare il numero di volte in cui
l'evento
'Testa' è uscito, nella sequenza di nlanci,
0 volte, 1 volta, etc., fino a n volte;
- si visualizzino infine i risultati
in due barplot nella stessa finestra grafica.
- Curiosità dell'aritmetica modulare,
mostrate direttamente con i seguenti comandi R (il link
è solo per chi vuole approfondire privatamente; ai fini del corso
le righe che seguono sono più che sufficienti):
- ( m = 21 )
- ( n = 1:m - 1 )
- (n + 2) %% m
- (n + 10) %% m
- (n + m) %% m
- ( nr = (n + 7) %% m )
- (nr - 7) %% m
- (nr - 9) %% m
Possiamo applicare queste proprietà per implementare
il famoso cifrario di Cesare, seppure, per semplicità,
con le 26 lettere dell'alfabeto
inglese invece che con le 21 di quello latino:
- letters[ ( (0:25) + 3 ) %% 25 + 1]
Ecco quindi dei problemi in C
- Si inizializzi un vettore di interi con i 26 valori
da 0 a 25; si scriva quindi una function del tipo
- void ciclaI (int n, int v[n], int pos)
che ruoti ciclicamente i valori di 'pos' posizioni
(anche negative).
- Si scriva una function che,
dato un carattere indicante una lettera dell'alfabeto
(minuscola o maiuscola: si metta un controllo al fine
di non agire su altri codici ascii), la ruoti ciclicamente
di 'pos' posizioni (pos=3 corrisponde al cifrario di Cesare;
pos=-3 alla sua decodifica).
Primitiva:
- char cifrarioC (char c, int pos)
- Si scriva quindi un programma che legga da riga di comando
(ovvero facendo uso di argv) un carattere che indichi se si vuol
fare la codifica ('c') o la decodifica ('d') seguito
dalle parole da criptare/decriptare, ad esempio
- ./cesare c veni vidi vici
→ il programma stampa quindi le parole codificate,
in maiuscolo e senza spazi.
(Alternativamente, al posto di 'c' o 'd', si può
mettere un intero che indichi di quante posizioni ruotare le
lettere)
Torna alla pagina del corso