# Note lezione (26/11/2020)
lezione precedente sul wiki del corso: http://sl-lab.it/dokuwiki/doku.php/pub:labprog:home
## Mem
Questo script funziona su linux, serve anche gnuplot.
```bash #!/bin/bash # https://stackoverflow.com/questions/7998302/graphing-a-processs-memory-usage
# IMPORTANTE! limitare mem altrimenti crasha pc LIMIT=2000000 # ok #LIMIT=20000 # troppo poco ulimit -m $LIMIT ulimit -v $LIMIT ulimit -a
#timeout 10 $* & # non va bene perché osserva il timeout invece del processo $* & PID=$!
echo === while
kill -0 $PID 2>/dev/null
do
echo $(date +%s) $(ps --pid $PID -o %mem=) #echo $(date +%s) $(ps --pid $PID -o drs=)
#ps --pid $PID -o pid=,%mem=,vsz=
done | tee prova.mon | gnuplot -p -e “set terminal x11 size 600,400; set yrange [0:3.2]; set ylabel 'mem'; set xlabel 'timestamp'; plot \”/dev/stdin\“ with linespoints title 'memory'”
```
```go package main
import (
"fmt" "math/rand" "time"
)
const DIM = 10000000 attenzione a non esagerare che un mio amico gli è morto il pc ;) const SLEEP = 5 nano
func main() {
attendo()
/* an int array with 5 elements */ var balance [DIM]int //var avg float32
rand.Seed(time.Now().Unix())
fmt.Println("riempio...") for i, _ := range balance { //fmt.Println(i) balance[i] = rand.Intn(10000) time.Sleep(SLEEP) // nano }
attendo()
// copy //fmt.Println(getAverage(balance))
// pointer fmt.Println(getAverage2(&balance))
attendo()
}
func attendo() {
fmt.Println("attendo...") time.Sleep(3 * time.Second) fmt.Println("fine attesa")
}
func getAverage(arr [DIM]int) float64 {
var avg float64 var sum int64
fmt.Println("calcolo...") for i, _ := range arr { sum += int64(arr[i]) time.Sleep(SLEEP) // nano }
avg = float64(sum) / DIM return avg
}
func getAverage2(arr *[DIM]int) float64 {
var avg float644 var sum int64
for i, _ := range arr { sum += int64(arr[i]) time.Sleep(SLEEP) // nano }
avg = float64(sum) / DIM return avg
}
```
## Note esercizi consegnati in settimana (scorsa lezione)
### problema lettura specifiche? o concezione di “specchio”?
```go func specchiaPunto(p *Punto) {
(*p).x = -p.x // MANTERREI STESSA SINTASSI A DESTRA E SINISTRA (*p).y = p.y // inutile perché non cambia lo stato return
} o func specchiaPunto(p *Punto) {
p.x = 0 - (p.x)
} o func funzSpecchio(p1 Punto) Punto { restituisce invece di modificare var p Punto p.x = -p1.x p.y = p1.y ««««««« return p } ``` invece di ```go func specchiaPunto(p *Punto) { (*p).x *= -1 corretto } o func specchiaPunto(p *Punto) {
(*p).x = -(*p).x // corretto
} ```
### passaggio per puntatore inutile
```go func main() {
var contaNumeri [10]int var parola string n := 0 fmt.Print("\nInserire una serie di parole terminate da \x22stop\x22:\n\n") for { fmt.Scan(&parola) if parola == "stop" { break } contaCifre(parola, &n, &contaNumeri) //A COSA SERVE n QUI? meglio fare un return nella fn } fmt.Printf("\n%d stringhe con cifre\n\n%v\n%v\n\n", n, numeri, contaNumeri)
}
func contaCifre(s string, n *int, x *[10]int) {
check := false for _, r := range s { if unicode.IsDigit(r) { appo, _ := strconv.Atoi(string(r)) (*x)[appo]++ check = true } } if check { (*n)++ }
} ```
### ottimizzazione
```go QUI PROBLEMA DI SPECIFICHE, ANDAVA MODIFICATO L'ARRAY SUL POSTO AT: anche, ma mi ero concentrato sull'invocazione multipla di len
func reverse(a [DIM]int) [DIM]int { passare per punt for i := 0; len(a)-i-1 != i; i++ { IO IN QUESTI CASI PREFERISCO IL > AL != AT: claro! a[i], a[len(a)-i-1] = a[len(a)-i-1], a[i] } return a } ``` ### delega (OK) ```go func countdown(c *Clock) { (*c).sec– if (*c).sec < 0 { (*c).sec = 59 changeMin(&c) “bastava” 'c' (è GIA' un puntatore, quindi '&c' è puntatore a puntatore)
}
}
func changeMin(c Clock) { idem (c).min– if (c).min < 0 { (c).min = 59 changeHour(&c) } } func changeHour(c *Clock) { idem (*c).hour–
if (***c).hour < 0 { // questo no se no non termina (***c).hour = 23 }
} ```
### compattabile
```go INVITA A FARE GLI ESERCIZI TUTTI E NELL'ORDINE IN CUI SONO PROPOSTI, LEGGENDO SUGGERIMENTI ECC diventa istruzione singola (c'era esercizio che suggeriva il modo)
BASTAVA 'num_comparsi[char]++' al posto di:
switch char { case '0': num_comparsi[0]++ case '1': num_comparsi[1]++ case '2': num_comparsi[2]++ case '3': num_comparsi[3]++ case '4': num_comparsi[4]++ case '5': num_comparsi[5]++ case '6': num_comparsi[6]++ case '7': num_comparsi[7]++ case '8': num_comparsi[8]++ case '9': num_comparsi[9]++ default: continue }
```
### compattabile valori di n da 1 a 9 (oppure array! c'era indicazione nel testo)
```go func carta(n int) (carta Carta) {
switch n % VALORI { case 0: carta.valore = "A" case 1: carta.valore = "2" case 2: carta.valore = "3" case 3: carta.valore = "4" case 4: carta.valore = "5" case 5: carta.valore = "6" case 6: carta.valore = "7" case 7: carta.valore = "8" case 8: carta.valore = "9" case 9: carta.valore = "10" case 10: carta.valore = "J" case 11: carta.valore = "Q" case 12: carta.valore = "K" }
switch n / VALORI { case 0: carta.seme = CUORI case 1: carta.seme = QUADRI case 2: carta.seme = FIORI case 3: carta.seme = PICCHE }
return
} ```
### trovare la variabile “inutilizzata”
```go func main() {
var s string var nStringhe int var count [DIM]int arr := [DIM]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
for { fmt.Scan(&s) if s == "stop" { break }
temp, ok := contaCifre(s) if !ok { continue }
for i, x := range temp { count[i] += x } nStringhe++ }
fmt.Println(nStringhe, "stringhe con cifre.") fmt.Println(arr) // per stampare una stringa formattata?!? fmt.Println(count)
}
poi probabilmente l'intenzione era di avere una “stringa” da stampare sotto a nStringhe… ``` ### compattare (err è bool) ```go if err == true { fmt.Println(“Errore, valore non valido. Esecuzione interrotta”) return } ``` ### lettura specifiche (o problemi implementazione) Era da fare SENZA array di appoggio ```go /* scambia il primo con l'ultimo dei valori in un array di dimensione DIM */ func switchFirstLast(originale *[DIM]int) { var ArrayDiAppoggio [DIM]int ArrayDiAppoggio = *originale originale[0] = ArrayDiAppoggio[DIM-1] originale[DIM-1] = ArrayDiAppoggio[0] } ``` ### non scalabile ```go var array [DIM]int array[0] = 1 array[1] = 2 array[2] = 3 array[3] = 4 array[4] = 5 array[5] = 6 meglio usare un for ``` ### ripensarlo? ```go func estraiCarta(n int) Carta {
var carta Carta
if n >= 0 && n <= 12 { carta.seme = "di cuori" } else if n >= 13 && n <= 25 { carta.seme = "di quadri" } else if n >= 26 && n <= 38 { carta.seme = "di fiori" } else if n >= 39 && n <= 51 { carta.seme = "di picche" } if n == 0 || n == 13 || n == 26 || n == 39 { carta.valore = "Asso" } else if n == 1 || n == 14 || n == 27 || n == 40 { carta.valore = "Due" } else if n == 2 || n == 15 || n == 28 || n == 41 { carta.valore = "Tre" } else if n == 3 || n == 16 || n == 29 || n == 42 { carta.valore = "Quattro" } else if n == 4 || n == 17 || n == 30 || n == 43 { carta.valore = "Cinque" } else if n == 5 || n == 18 || n == 31 || n == 44 { carta.valore = "Sei" } else if n == 6 || n == 19 || n == 32 || n == 45 { carta.valore = "Sette" } else if n == 7 || n == 20 || n == 33 || n == 46 { carta.valore = "Otto" } else if n == 8 || n == 21 || n == 34 || n == 47 { carta.valore = "Nove" } else if n == 9 || n == 22 || n == 35 || n == 48 { carta.valore = "Dieci" } else if n == 10 || n == 23 || n == 36 || n == 49 { carta.valore = "J" } else if n == 11 || n == 24 || n == 37 || n == 50 { carta.valore = "Q" } else if n == 12 || n == 25 || n == 38 || n == 51 { carta.valore = "K" } return carta
}
```
### switchabile ma cmq BASTA UNA SOLA ISTRUZIONE
BASTAVA una cosa tipo: ```'ripetizioniNumeri[strInput[i]-'0']++' ```(a meno di una conversione)
```go
if strInput[i] == '0' { ripetizioniNumeri[0]++ } else if strInput[i] == '1' { ripetizioniNumeri[1]++ } else if strInput[i] == '2' { ripetizioniNumeri[2]++ } else if strInput[i] == '3' { ripetizioniNumeri[3]++ } else if strInput[i] == '4' { ripetizioniNumeri[4]++ } else if strInput[i] == '5' { ripetizioniNumeri[5]++ } else if strInput[i] == '6' { ripetizioniNumeri[6]++ } else if strInput[i] == '7' { ripetizioniNumeri[7]++ } else if strInput[i] == '8' { ripetizioniNumeri[8]++ } else if strInput[i] == '9' { ripetizioniNumeri[9]++ }
```
## Note su slice e mappe
#### Dichiarazione di una map:
sintassi: `var map1 map[keytype]valuetype`
es: `var map1 map[string]int`
#### Allocazione(creazione)/inizializzazione di una map
sintassi: `map1 := make(map[keytype]valuetype)` o anche: `map1 := map[keytype]valuetype{} tra {} ci può essere una lista di coppie chiave-valore` es: `map1 := make(map[string]float64)` o anche: `map1 := map[string]float64{} map1 := map[string]float64{“zero” : 0., “uno” : 1.} }` #### Dichiarazione di una slice: sintassi: `var slice []type` es: `var slice []int` #### Allocazione(creazione)/inizializzazione di una slice sintassi: ```go slice := make([]type, length, capacity) slice := make([]type, length) la capacità può non essere specificata
slice := []type{} tra {} ci può essere una lista di valori ``` es: ```go slice := make([]int, 0, 5) slice := []int{} slice := []int{1, 2, 3, 4} ``` #### Differenza tra ```new``` e ```make```: - ```new(T)``` alloca memoria per un nuovo elemento di tipo T e restituisce il suo indirizzo, quindi un valore di tipo *T (un puntatore) - ```make(T)``` restituisce un valore di tipo T; si applica solo ai tipi riferimento predefiniti: slice, mappe (e canali). In altre parole, ```new``` alloca, ```make``` inizializza #### Funzioni built-in per slice (vedi documentazione packages, sotto builtin) - ```func append(slice []Type, elems …Type) []Type``` es: ```go slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice…) ``` - ```func copy(dest, src []Type) int``` ## Note generali (slegate dagli esercizi) Non è necessario utilizzare una variabile di appoggio quando dovete scambiare di valore due variabili (*nota: non è possibile farlo in tutti i linguaggi, ma in questo si*) ```go a := 1 b := 2 a, b = b, a fantastico! ```
—
I calcoli devono essere fatti dal computer, non da voi. Cercate sempre di trovare un *pattern/formula* per risolvere i prolemi che si presentano, sopratutto se sono di assegnamento, tipo: si deve inizializzare un array di 5 elementi con i valori 0..4 → usate un for, non inizializzate ogni posizione in modo esplicito
Lo stesso discorso vale per lo switch: dove si può compattare, si compatta, senza mai fare calcoli espliciti.
—
Per stampare le rune:
```go fmt.Printf(“%c”, <carattere>) oppure fmt.Println(string(<carattere>)) ``` — ## FAQ ### NumToText (svolto insieme) #### mappe - costruzione e uso Scrivere un programma ```num2text.go``` per convertire un numero intero non negativo nella sequenza delle parole corrispondenti alle sue cifre. Il programma legge un intero non negativo da standard input, per ogni nuova (non incontrata finora) cifra del numero chiede il nome corrispondente (e alimenta un dizionario), e infine stampa la sequenza delle parole corrispondenti alle sue cifre. Ad esempio, per il numero 203, il programma stampa due - zero - tre #### Esempio di esecuzione ``` $ go run num2text.go un numero: 622 parola per 2 ? due parola per 6 ? sei sei - due - due ``` ```go package main import “fmt” func main(){ var m map[int]string m = make(map[int]string) var n int var nome string fmt.Print(“Inserire un numero intero: ”) fmt.Scan(&n) parola := “” for n!=0{ cifra:=n%10 fmt.Println(cifra)
_,ok:=m[cifra] // cerca valore mappato di 'cifra', se non lo trova restituisce false if !ok{ fmt.Printf("parola per %d? ",cifra) fmt.Scan(&nome) m[cifra]=nome } parola = m[cifra] + " - " + parola n=n/10 } fmt.Println(parola[:len(parola)-3]) // fmt.Println(m)
} ```
### Vocali
Nelle mappe, non c'è di norma un ordinamento delle chiavi
—
Potete implementare una funzione che stampa la mappa, al posto di usare `Print(mappa)`
—
Per la stampa ordinata: potete usare una stringa di appoggio, sapete già quali sono le vocali e in quale ordine sono
### Anagrammi
Per “estrarre” una runa da una stringa: chiedetevi come sono “definite” le stringhe..
—
Linea di comando = parametri del `main`
### Galleggianti
—
### Operazioni_slice
—
### Appello
—
### Temperature
—
### Posizioni_parole