Skip to content
Snippets Groups Projects
Unverified Commit 1afabbee authored by Andrea Trentini's avatar Andrea Trentini
Browse files

lab08

parent a0106aa7
Branches
No related tags found
No related merge requests found
Lab08.md 0 → 100644
# Lab 08 - mappe
# sorgenti (inclusi nomi sbagliati) consegnati: 218
# quanti di ogni esercizio:
```
15 quadrati.go
14 es7.go
14 es2.go
13 es12.go
13 es10.go
12 es8.go
11 array.go
10 punto_bis.go
10 ordini.go
9 countdown.go
9 contaLettere.go
8 extractions.go
7 usaStandard.go
7 polinomio.go
7 estraiData_bis.go
7 dado_bis.go
6 stampaAlternata.go
5 usoLeSlice.go
4 giornoSettimana.go
4 conta_cifre.go
4 carte.go
3 strings2slice.go
3 scambio.go
3 es6.go
3 es5.go
3 es4.go
3 es3.go
2 puntatori.go
2 clessidra.go
1 usastandard.go
1 puntatore2.go
1 estraiDATA_bis.go
1 es9.go
1 es11.go
1 es1.go
1 black_jack.go
```
---
# Esercizi Go
## Note iniziali
- convenzione nomi file (dir, file, mod: nomi uguali)
- nella dir dell'esercizio, lanciare il comando:\
```go mod init <nome programma senza estensione>```
## Richiami sulle mappe
### Dichiarazione di una mappa (viene creata una mappa "zero-value", cioè nil)
Sintassi:
```go
var mapName map[keyType]valueType
```
Esempio:
```go
var map1 map[string]int
```
**Nota**. A differenza delle slice, una mappa deve essere inizializzata (vedi qui sotto come) prima di poter aggiungervi elementi, altrimenti si ottiene un errore run-time:\
<tt>panic: assignment to entry in nil map</tt>
### Inizializzazione di una mappa
Sintassi:
```go
mapName := make(map[keyType]valueType)
```
o anche:
```go
mapName := map[keyType]valueType{} // tra {} ci può essere una lista di coppie chiave-valore
```
Esempi:
```go
map1 := make(map[string]float64)
map1 := map[string]float64{}
map1 := map[string]float64{"zero" : 0., "uno" : 1.}
```
### Operazioni su mappe
Inserimento o aggiornamento di un elemento in una mappa m (si fanno nello stesso modo, non occorre controllare se la chiave c'era già):
```go
m[key] = elem
```
Accesso a un elemento di una mappa:
```go
elem = m[key]
```
Cancellazione di un elemento da una mappa:
```go
delete(m, key)
```
Verifica della presenza di una chiave in una mappa:
```go
element, ok = mappa[key] //se key c'è in mappa, ok è true; altrimenti ok è false e elemt è zero-value
```
Per verificare se due mappe sono uguali, vedete la funzione `DeepEqual` del package `reflect`.
### Usi delle mappe
- per **contare**: `map[Type]int`
ad esempio quante occorrenze di ogni stringa in un testo: `map[string]int`
- per creare **cataloghi**: `map[string/int] string/struct`
- per creare **dizionari**: `map[string]string`
- per **raggruppare** valori/oggetti in base a una caratteristica: `map[tipo caratteristica][]tipo dei valori/oggetti`, quindi una mappa chiave - slice.
- ecc.
---
## Esercizi sulle mappe
### Lunghezze (mappe)
Scrivere un programma lunghezze.go che legge riga per riga un testo da standard input (potete usare la ridirezione), terminato da EOF, e stampa quante parole ci sono di lunghezza 1, quante di lunghezza 2, ecc.
Il programma è dotato di una funzione
```
func aggiornaConteggio(m map[int]int, riga string)
```
che aggiorna la mappa dei conteggi e che deve essere usata dal main.
nomefile: lunghezze.go
### Vocali (mappe)
Scrivere un programma vocali.go che analizza un testo e conta le occorrenze delle vocali (sia minuscole che maiuscole, ma non le accentate) nel testo e stampa, ma solo per le vocali presenti nel testo, il numero di volte che le vocali stesse sono presenti nel testo.
In particolare il programma è dotato di:
- una funzione
```
func contaVocali(s string, vocali map[rune]int)
```
per contare le occorrenze delle diverse vocali (sia minuscole che maiuscole - vedi es sotto) in tutte le stringhe che le vengono passate. La funzione, data una stringa s e una mappa vocali, aggiorna opportunamente la mappa vocali aggiungendo eventuali vocali non ancora presenti / incrementandone i valori.
Nota: per individuare le vocali e aggiornare la mappa <tt>vocali</tt> usate uno switch con un solo case o un if, sempre con un solo caso, che ovviamente sarà parametrico nelle vocali.
- una funzione
```
func main()
```
che legge una riga di testo da standard input e produce una mappa tra vocali presenti nel testo e il numero delle loro occorrenze nel testo, e la stampa.
#### Esempio
Se l'input è:
```
jdhkas c'è dkasjhkdjashkdh askdh ksah @@@ €€€ ### Ħ wi) Ø qwqwe qwyewquteuqwte q 312312 2312wweqe €łłŧŧŧŧŧ sdasdas AA JKJLKLJLKJ LIIIIII u ù aeiou AEIO
```
L'output è (salvo l'ordine di stampa):
```
o : 1
E : 1
u : 4
e : 7
A : 3
I : 7
O : 1
a : 8
i : 2
```
Come si potrebbero stampare le vocali con le loro occorrenze in ordine alfabetico?
Scrivere una seconda versione vocali_bis.go che produce l'output in ordine:
```
A : 3
E : 1
I : 7
O : 1
a : 8
e : 7
i : 2
o : 1
u : 4
```
nomefile: vocali.go
nomefile: vocali_bis.go
### Anagrammi (volendo mappe, ma anche slice)
Scrivere un programma anagrammi.go che legge due stringhe da linea di comando e valuta se le due stringhe sono una l'anagramma dell'altra (la seconda stringa è formata da una permutazione dei caratteri della prima)
In particolare il programma è dotato di:
- una funzione
```
func isAnagram(s1, s2 string) bool
```
che restituisce true se le due stringhe sono una l'anagramma dell'altra, false altrimenti
- una funzione
```
func main()
```
che legge due parole p1 e p2 da linea di comando e stampa uno dei due messaggi:
"p1 e p2 sono anagrammi" o "p1 e p2 non sono anagrammi"
NB: **che caratteristiche ha un anagramma?**
C'è in Go una struttura di dati (array, struct, slice, map) che
si presta a rappresentare i dati di una stringa s1 che servono
ad individuare se è un anagramma di un'altra stringa s2?
Se sì, quale e coma la uso? Se no, come imposto la soluzione?
In assenza di esattamente due parametri sulla linea di comando il programma stampa: `input errato`
nomefile: anagrammi.go
### NumToText (mappe)
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
```
nomefile: num2text.go
### Capoluoghi (mappe)
Scrivere un programma capoluoghi.go che legge da standard input (usate la ridirezione dal file [capoluoghi](Lab08/capoluoghi.csv)) una serie di informazioni sui capoluoghi organizzate su righe, nel seguente formato:
Nome,Sigla,Regione,Popolazione,Superficie,Densita,Altitudine
e memorizza Nome, Sigla, Regione, Superficie in modo sia possibile ottenere la stampa delle informazioni relative a capoluoghi, le cui sigle sono state passate da linea di comando.
Nome, Sigla, Regione sono stringhe; Popolazione,Superficie, Densità, Altitudine sono sempre int.
La prima riga è l'intestazione e le successive contengono i dati, separati da virgole, un riga per capoluogo.
Il programma deve essere dotato di una struct Capoluogo con campi Nome, Sigla, Regione, Superficie, in quest'ordine.
NB: discorso struct "ridondante in apparenza"
#### Esempio di esecuzione
```
$ ./capoluoghi MI < capoluoghi.csv
{MILANO MI LOM 1371498 181 7549 122}
```
nomefile: capoluoghi.go
### Regioni (mappe)
Scrivere un programma regioni.go che che legge da standard input (usate la ridirezione dal file [capoluoghi](Lab08/capoluoghi.csv)) una serie di informazioni sui capoluoghi di provincia organizzate su righe, nel seguente formato:
Nome,Sigla,Regione,Popolazione,Superficie,Densita,Altitudine
e memorizza nome e regione in modo che sia possibile ottenere la stampa della lista dei capoluoghi di provincia delle regioni i cui nomi sono stati forniti da linea di comando.
nomefile: regioni.go
### Posizioni parole (mappe)
Scrivere un programma posizioni_parole.go che legge una sequenza di stringhe da standard input e produce su standard output, per ogni stringa, la lista delle posizioni in cui essa compare nella sequenza (partendo dalla posizione 0).
Nota: per terminare l’input da tastiera, premere invio e la combinazione di tasti Ctrl D, che corrisponde a EOF (end of file) per lo standard input.
In caso di dubbi su come gestire la fine dell’input nel programma, consultare la documentazione della funzione Scan, funzione che, oltre a salvare i valori letti, restituisce dei valori.
#### Esempio:
```
$ go run posizioni_parole.go
scrivi parole (ctrl D per terminare)
O bella ciao bella ciao bella ciao ciao ciao
Una mattina mi sono alzato
map[O:[0] Una:[9] alzato:[13] bella:[1 3 5] ciao:[2 4 6 7 8] mattina:[10] mi:[11] sono:[12]]
```
nomefile: posizioni_parole.go
---
## Progetti
### Progetto Stack (slice)
Creare un programma stack.go che gestisca uno stack (pila)
generico (numero arbitrario di posizioni) di valori float
Lo stack e` una struttura dati con le seguenti caratteristiche:
- mantiene nella prima posizione (detta testa) il valore piu' recente
- e` possibile accedere sempre e solo alla sua testa
Le operazioni disponibili sullo stack sono:
- push: aggiunge un valore in testa allo stack
- pop: rimuove il valore in testa allo stack e lo restituisce
- top (o peek): restituisce il valore in testa allo stack senza rimuoverlo
- empty: restituisce vero se lo stack e` vuoto, falso altrimenti
Per ciascuna operazione creare una funzione, usando
nomi maiuscoli (Push, Pop, ...).
Implementare poi una funzione main() che chieda ripetutamente
all'utente quale operazione vuole richiedere (push/pop/top/empty/quit),
nel caso di push chieda anche il valore da aggiungere,
stampi ogni volta il risultato e lo stack, e termini con quit.
#### Esempio
```
Operazione (push/pop/top/empty/quit)?
push
valore?
4
[4]
Operazione (push/pop/top/empty/quit)?
push
valore?
5
[5 4]
Operazione (push/pop/top/empty/quit)?
pop
testa 5
[4]
Operazione (push/pop/top/empty/quit)?
top
testa 4
[4]
Operazione (push/pop/top/empty/quit)?
quit
```
Nota: per interrompere un for da uno switch annidato,
occorre etichettare il for e aggiungere l'etichetta
al break:
```go
myloop:
for ....{
....
break myloop
}
```
Versione 1: Usare per lo stack una variabile globale e
per semplicita` implementare lo stack con una slice in
cui la testa dello stack e` l'ultimo elemento (quello in
posizione len(stack)-1).
Versione 2: implementare lo stack con una slice in cui la
testa dello stack e` il primo elemento (quello in posizione 0)
Suggerimento: e` possibile appendere a una slice s1 un'altra
slice s2 usando ... per espandere s2 a una lista di argomenti:
append(s1, s2...)
e creando una slice che contenga la nuova testa:
[]float64{val}
Versione 3: Usare per lo stack una variabile locale del
main e quindi passarlo come parametro alle funzioni
(usare puntatori).
Per accedere a un elemento di una slice di cui si ha il
puntatore la sintassi e`:
(*stack)[i]
nomefile: stack.go
---
### Progetto Calcolatrice RPN
Creare una dir stack in cui spostare la versione 3 del programma `stack.go`, di cui dovete commentare la funzione main().
Creare nella stessa dir (stack) un programma RPN.go
e (con il comando go mod init RPN) un file go.mod con il seguente contenuto:
module RPN
go 1.17
Per compilare il tutto dovrete dare (nella dir stack) il comando
```
$ go build
```
Il programma deve realizzare una calcolatrice in
notazione polacca inversa (RPN), o notazione postfissa
(https://it.wikipedia.org/wiki/Notazione_polacca_inversa),
notazione in cui prima si inseriscono gli operandi e
poi gli operatori: ad esempio 3 4 + 5 * invece che
(3 + 4) * 5, e 3 4 5 * + invece di 3 + 4 * 5.
La calcolatrice deve disporre delle quattro operazioni
aritmetiche (+ - * /) e operare su valori float64.
Il funzionamento è il seguente:
ripetere:
- leggere un input dall'utente
- se è un numero, lo mette in testa allo stack (una push)
- se è un operatore,
- preleva gli operandi dallo stack (due pop)
- esegue l'operazione corrispondente all'operatore (+ - * /)
- salva il risultato nello stack (push)
- condizione di uscita: inserimento di "q" (quit)
- condizioni di errore: mancanza di operandi
Nel caso l'input non sia nè un numero nè un operatore nè
"q", il programma lo ignora (non occorre che segnali errore).
Per verificare se l'input è un numero, utilizzare la funzione
```go
val, err := strconv.ParseFloat(input, 64)
```
Nel caso err sia nil, l'input è un numero che verrà salvato
in val.
#### Esempio
```
$ go run RPN.go
Next? (+, -, *, /, q o un numero) 3
[3]
Next? (+, -, *, /, q o un numero) 5
[3 5]
Next? (+, -, *, /, q o un numero) 7
[3 5 7]
Next? (+, -, *, /, q o un numero) *
[3 35]
Next? (+, -, *, /, q o un numero) +
[38]
Next? (+, -, *, /, q o un numero) -
not enough data
[38]
Next? (+, -, *, /, q o un numero) q
```
Creare una seconda versione RPN2.go in cui l'espressione
da valutare sia fornita da linea di comando (os.Args)
invece che da standard input (cioe` tastiera).
In questo caso se l'espressione contiene moltiplicazioni,
l'asterisco va messo tra apici ('*') o tra virgolette ("*").
nomefile: RPN.go
### Progetto Black Jack (slice)
Riprendere il progetto del Black Jack, dove una carta
era una struct con i campi seme (string) e valore (string).
Definire una funzione main() per testare man mano le funzioni
che seguono.
Modificare la funzione mazzoPoker che crea e restituisce un
mazzo di 52 carte da poker, usando una slice invece che un array,
in modo da poter "distribuire" carte dal mazzo.
Modificare quindi anche la funzione mischia che, dato un mazzo di carte
(di dimensione arbitraria), lo rimescola in modo random
(occorre usare anche qui le slice).
Definire una funzione preleva che, dato un mazzo di carte,
restituisce la carta che si trova in cima e la toglie dal mazzo.
Implementare un simulatore di BJ
(https://it.wikipedia.org/wiki/Blackjack),
che consenta ad un giocatore singolo di giocare contro
il PC (che rappresenta il mazziere).
Utilizzare come mazzo due mazzi da poker.
nomefile: blackjack.go
---
## Esercizi supplementari
### Stats temperature (ripasso slice)
Scrivere un programma temperature.go che legge delle temperature (int) da tastiera e termina quando il valore letto è 999.
Il programma deve stampare:
- la media
- la mediana
- il numero di temperature sotto la media delle temperature stesse.
- le tre temperature più basse (se ci sono almeno 3 temperature)
- le tre temperature più alte (se ci sono almeno 3 temperature)
Nota 1: la mediana di un insieme di dati è data, nel caso ci sia un numero dispari di dati, dal dato centrale dei dati ordinati per valore (ad es. crescente), altrimenti dalla media dei due dati centrali.
Nota 2: Utilizzare la funzione `Ints(a []int)` del pacchetto `sort` per ordinare in modo crescente le temperature.
nomefile: temperature.go
### Appello (ripasso slice)
Scrivere un programma appello.go che legge da linea di comando una sequenza di nomi e li stampa in ordine alfabetico.
#### Esempio
```
$ go run appello.go Rita Carlo Matteo Ada
[Ada Carlo Matteo Rita]
```
Nota: Utilizzare la funzione `Strings(a []string)` del pacchetto `sort` per ordinare in modo crescente i nomi.
nomefile: appello.go
### Galleggianti (sfida per i più arditi)
Scrivete un programma galleggianti.go che legga da standard input due interi r, c, seguiti da una matrice di r righe e c colonne contenente lettere maiuscole e asterischi, e che stampi in output la matrice che si ottiene da quella in input mandando verso il basso le lettere e facendo "galleggiare" gli asterischi, cioè mandandoli verso l'alto.
Fornire in input una riga della matrice alla volta, e sfruttare la funzione `strings.Split(s, " ")` (vedi documentazione) per popolare le righe della matrice.
Si assuma che ogni riga di input contenga esattamente c caratteri, separati da spazi (non sono richiesti controlli in tal senso).
#### Esempio
Se la matrice è data da
```
V * S
* * B
K S *
* * *
```
il programma dovrà stampare la matrice seguente:
```
* * *
* * *
V * S
K S B
```
nomefile: galleggianti.go
Citta,Prov,Reg,PopolazioneResidenti,Superficie,DensitaAbitanti,Altitudine
ROMA,RM,LAZ,2761632,1287,2145,20
MILANO,MI,LOM,1371498,181,7549,122
NAPOLI,NA,CAM,914758,118,7691,17
TORINO,TO,PIE,848885,130,6527,239
PALERMO,PA,SIC,630828,160,3928,14
GENOVA,GE,LIG,560688,240,2333,19
BOLOGNA,BO,EMR,392203,140,2784,54
FIRENZE,FI,TOS,36715,102,3588,50
BARI,BA,PUG,31614,117,2693,5
Catania,CT,SIC,298324,182,1632,7
Verona,VR,VEN,257274,198,1293,59
VENEZIA,VE,VEN,254661,415,612,2
Messina,ME,SIC,220094,213,103,3
Padova,PD,VEN,208732,93,2244,12
Prato,PO,TOS,200762,97,2062,61
TRIESTE,TS,FVG,200594,85,2357,2
Brescia,BS,LOM,19685,90,2179,149
Parma,PR,EMR,196655,260,755,57
Taranto,TA,PUG,189171,249,757,15
Modena,MO,EMR,185644,183,1013,34
Reggio Calabria,RC,CAL,1718,239,719,31
Reggio Emilia,RE,EMR,169029,230,733,58
PERUGIA,PG,UMB,163598,449,364,493
Ravenna,RA,EMR,15608,653,239,4
Livorno,LI,TOS,154177,104,1472,3
Rimini,RN,EMR,150051,135,1105,5
CAGLIARI,CA,SAR,148881,84,176,6
Foggia,FG,PUG,146379,509,287,76
Ferrara,FE,EMR,131091,405,324,9
Salerno,SA,CAM,128105,59,214,4
Latina,LT,LAZ,127221,277,458,21
Monza,MB,LOM,122099,33,369,162
Sassari,SS,SAR,121657,547,222,225
Bergamo,BG,LOM,120207,40,2994,249
Pescara,PE,ABR,119406,34,3478,4
TRENTO,TN,TAA,118509,157,751,194
Forlì,FC,EMR,116861,228,512,34
Siracusa,SR,SIC,116447,207,560,17
Vicenza,VI,VEN,110675,80,1373,39
Terni,TR,UMB,107314,212,505,130
Bolzano,BZ,TAA,107025,52,2047,262
Piacenza,PC,EMR,102902,118,870,61
Novara,NO,PIE,101727,103,987,162
ANCONA,AN,MAR,98664,124,790,30
Udine,UD,FVG,97761,57,1709,113
Andria,BT,PUG,97173,402,241,151
Arezzo,AR,TOS,96672,384,251,296
Pesaro,PU,MAR,95753,152,627,11
Lecce,LE,PUG,95253,238,399,49
Barletta,BT,PUG,92466,149,619,15
La Spezia,SP,LIG,92216,51,1794,3
Alessandria,AL,PIE,90987,203,447,95
Pisa,PI,TOS,89828,185,485,4
Pistoia,PT,TOS,89501,236,379,67
Lucca,LU,TOS,89219,185,480,19
CATANZARO,CZ,CAL,85544,112,759,320
Treviso,TV,VEN,84793,55,1526,15
Como,CO,LOM,83626,37,2252,201
Brindisi,BR,PUG,83169,333,250,13
Grosseto,GR,TOS,8144,473,172,10
Varese,VA,LOM,78875,54,1438,382
Asti,AT,PIE,73539,151,486,123
Caserta,CE,CAM,73068,54,1351,68
Ragusa,RG,SIC,7269,444,163,502
Pavia,PV,LOM,71159,63,1125,77
Cremona,CR,LOM,70943,70,1006,45
L'AQUILA,AQ,ABR,69508,473,147,714
Massa,MS,TOS,66423,93,708,65
Viterbo,VT,LAZ,65987,406,162,326
POTENZA,PZ,BAS,64786,175,369,819
Trapani,TP,SIC,64486,273,236,3
Cosenza,CS,CAL,63713,37,1683,238
Matera,MT,BAS,59869,392,153,401
Caltanissetta,CL,SIC,59063,421,140,568
Savona,SV,LIG,58563,65,897,4
Crotone,KR,CAL,58478,181,321,8
Benevento,BN,CAM,56939,130,435,135
Cuneo,CN,PIE,55813,119,466,534
Agrigento,AG,SIC,55636,243,228,230
Trani,BT,PUG,54838,103,530,7
Siena,SI,TOS,53724,118,453,322
Avellino,AV,CAM,52568,30,1721,348
Teramo,TE,ABR,51891,152,340,432
Pordenone,PN,FVG,51818,38,1356,24
Rovigo,RO,VEN,50379,108,463,7
Mantova,MN,LOM,48648,63,762,19
Chieti,CH,ABR,48612,59,816,330
CAMPOBASSO,CB,MOL,47334,56,844,701
Lecco,LC,LOM,4706,45,1043,214
Ascoli Piceno,AP,MAR,46079,158,292,154
Rieti,RI,LAZ,45624,206,221,405
Vercelli,VC,PIE,45141,79,566,130
Lodi,LO,LOM,44793,41,1083,87
Frosinone,FR,LAZ,44003,46,939,291
Biella,BI,PIE,42761,46,916,420
Imperia,IM,LIG,4206,45,927,10
Macerata,MC,MAR,4082,92,441,315
Fermo,FM,MAR,35932,124,289,319
Belluno,BL,VEN,35436,147,241,383
Nuoro,NU,SAR,34105,192,178,549
Gorizia,GO,FVG,33837,41,820,84
AOSTA,AO,VDA,33186,21,1551,583
Vibo Valentia,VV,CAL,31407,46,674,476
Oristano,OR,SAR,30541,84,361,9
Verbania,VB,PIE,29952,37,799,197
Carbonia,SU,SAR,2639,145,181,111
Enna,EN,SIC,25775,358,72,931
Sondrio,SO,LOM,2118,20,1015,307
Isernia,IS,MOL,20771,69,300,423
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment