esercizi 12 dic 2019

parent 32957cc5
# Esercizi 12 dicembre 2019
## Note prima degli esercizi
- Caricarli su https://upload.di.unimi.it
- Molte volte nel testo dell'esercizio si specificano dei vincoli sull'input. Occorre verificarne sempre la veridicità. Nel caso in cui l'input inserito non rispetti il vincolo, stampare un messaggio di errore e chiederne il reinserimento, fino a quando non viene fornito un input valido. Ad esempio, se il programma *pippo.go* attende in input un numero pari, un possibile scenario potrebbe essere il seguente:
```console
$./pippo
Inserire un numero n pari:
3
Numero non valido
Inserire un numero n pari:
5
Numero non valido
Inserire un numero n pari:
2
```
- Se non vengono specificati vincoli sull'input, si può assumere che sia privo di errori
- Evitare di inserire stampe non richieste
- Ricordatevi di usare sempre `gofmt` per formattare correttamente il file
- Se un esercizio vi sembra troppo difficile da risolvere al primo colpo, provate a "scomporlo" in sottoproblemi più semplici e a risolverlo per passi
- mi raccomando date "nomi parlanti" alle variabili
## Continuo di ``tartaruga.go``
Riprendete l'esercizio ``tartaruga.go`` di due lezioni fa e modificate il programma in modo che venga evidenziata nella stampa il percorso seguito dalla tartaruga stessa. Riflettete bene su come modificare metodi / strutture dati utilizzate. In particolare, chiedetevi **dove** memorizzare il percorso seguito.
*Suggerimento*: utilizzate matrici / array bidimensionali ``mappa := [][]string``
### Soluzione 1
```go
package main
import (
"fmt"
"os"
"strconv"
)
type Turtle struct {
x, y int
direction Direction
}
type Direction int
const (
Nord Direction = iota
Est
Sud
Ovest
)
var MaxX, MaxY int
var cacca [][]bool
// 🐢🍂🌷🌼🌻💩
func status(t *Turtle) {
dirstring := [4]string{"Nord", "Est", "Sud", "Ovest"}
fmt.Printf("Posizione: (%d,%d)\nDirezione: %s\n", (*t).x, (*t).y, dirstring[(*t).direction])
for y := 0; y < MaxY; y++ {
for x := 0; x < MaxX; x++ {
if x == (*t).x && y == MaxY-(*t).y-1 {
fmt.Print("🐢")
} else if cacca[x][MaxY-y-1] {
fmt.Print("💩")
} else {
fmt.Print("🌼")
}
}
fmt.Println()
}
}
func forward(t *Turtle, steps int) {
for i:=0;i<steps;i++ {
switch (*t).direction {
case Nord:
(*t).y = ((*t).y + 1) % MaxY
case Est:
(*t).x = ((*t).x + 1) % MaxX
case Sud:
(*t).y = ((*t).y + MaxY - 1) % MaxY
case Ovest:
(*t).x = ((*t).x + MaxX - 1) % MaxX
}
cacca[t.x][t.y]=true
}
}
func backward(t *Turtle, steps int) {
for i:=0;i<steps;i++ {
switch (*t).direction {
case Nord:
(*t).y = ((*t).y + MaxY - 1) % MaxY
case Est:
(*t).x = ((*t).x + MaxX - 1) % MaxX
case Sud:
(*t).y = ((*t).y + 1) % MaxY
case Ovest:
(*t).x = ((*t).x + 1) % MaxX
}
}
}
func right(t *Turtle) {
(*t).direction = ((*t).direction + 1) % 4
}
func left(t *Turtle) {
(*t).direction = ((*t).direction + 3) % 4
}
func main() {
var (
t Turtle
steps int
)
i := 1
MaxX, _ = strconv.Atoi(os.Args[1])
MaxY, _ = strconv.Atoi(os.Args[2])
cacca=make([][]bool, MaxX)
for i,_:=range cacca {
cacca[i]=make([]bool, MaxY)
}
cacca[0][0]=true
for i > 0 {
status(&t)
fmt.Print("1. Avanti\n2. Indietro\n3. Ruota a destra\n4. Ruota a sinistra\n0. Esci\n")
fmt.Scanf("%d\n", &i)
switch i {
case 1:
fmt.Print("Numero di passi: ")
fmt.Scanf("%d\n", &steps)
forward(&t, steps)
case 2:
fmt.Print("Numero di passi: ")
fmt.Scanf("%d\n", &steps)
backward(&t, steps)
case 3:
right(&t)
case 4:
left(&t)
}
}
}
```
### Soluzione "interattiva"
```go
package main
import (
"fmt"
)
type dir int
type turtle struct {
x, y int
dir dir
}
type poop struct {
x, y int
}
const (
nord dir = iota
est
sud
ovest
)
const l int = 15
func status (t turtle, poops []poop) {
dirstring := [4]string {"Nord","Est","Sud","Ovest"}
fmt.Printf("\nposizione: %d; %d | direzione: %s | n° di cacche: %d\n", t.x, t.y, dirstring[t.dir], len(poops))
}
func forward (passi int, t *turtle) {
switch (*t).dir {
case nord:
(*t).x = ((*t).x + passi) % l
case est:
(*t).y = ((*t).y + passi) % l
case sud:
(*t).x = ((*t).x - passi + l) % l
case ovest:
(*t).y = ((*t).y - passi + l) % l
}
}
func backward (passi int, t *turtle) {
switch (*t).dir {
case nord:
(*t).x = ((*t).x - passi + l) % l
case est:
(*t).y = ((*t).y - passi + l) % l
case sud:
(*t).x = ((*t).x + passi) % l
case ovest:
(*t).y = ((*t).y + passi) % l
}
}
func right (t *turtle) {
(*t).dir = ((*t).dir + 1) % 4
}
func left (t *turtle) {
(*t).dir = ((*t).dir + 3) % 4
}
func makePoop (t turtle, poops *[]poop) {
var p poop
p.x, p.y = t.x, t.y
*poops = append(*poops, p)
}
func griglia (t turtle, poops []poop) {
for i := l; i >= -1; i-- {
for j := l; j >= -1; j-- {
if i == -1 || i == l {
fmt.Print("--")
} else {
if j == -1 {
fmt.Print(" |")
} else if j == l {
fmt.Print("| ")
} else if t.x == i && t.y == l - j - 1 {
fmt.Print("@°")
} else {
var flag bool
flag = false
for k := 0; k < len(poops); k++ {
if poops[k].x == i && poops[k].y == l - j - 1 {
flag = true
break
}
}
if flag {
fmt.Print("**")
} else {
fmt.Print(" ")
}
}
}
}
fmt.Println()
}
}
func main () {
var t turtle
t.x = l / 2
t.y = l / 2
var c,p int
var poops []poop
poops = make([]poop, 0)
fmt.Print("\ncomandi:\n\n1 -> avanti\n2 -> indietro\n3 -> ruota a dx\n4 -> ruota a sx\n5 -> fai la cacca\n0 -> esci\n\n")
for i := 0; i < 1; {
griglia(t, poops)
fmt.Print("comando: ")
fmt.Scan(&c)
switch c {
case 1:
fmt.Print("n° di passi: ")
fmt.Scan(&p)
if p > l {
fmt.Println("\nè una tartaruga, vacci piano\n")
} else if p < 0 {
fmt.Println("\ndai, fai il serio\n")
} else {
forward(p, &t)
status(t, poops)
}
case 2:
fmt.Print("n° di passi: ")
fmt.Scan(&p)
if p > l {
fmt.Println("\nè una tartaruga, vacci piano\n")
} else if p < 0 {
fmt.Println("\ndai, fai il serio\n")
} else {
backward(p, &t)
status(t, poops)
}
case 3:
right(&t)
status(t, poops)
case 4:
left(&t)
status(t, poops)
case 5:
var flag bool
flag = true
for i := 0; i < len(poops); i++ {
if poops[i].x == t.x && poops[i].y == t.y {
flag = false
break
}
}
if flag {
makePoop(t, &poops)
status(t, poops)
} else {
fmt.Println("\nl'hai già fatta qua\n")
}
case 0:
fmt.Println("\nadios\n")
i += 1
default:
fmt.Println("\ncomando non valido\n")
}
}
}
```
## Digressione "make"
```go
//scrivere un programma che appenda elementi ad una slice, e che stampi a distanza di un intervallo di tempo
//i vari valori che la slice assume nel tempo
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
var s []int
now := time.Now().UnixNano()
rand.Seed(now)
//d,_=time.ParseDuration("1.5s")
//fmt.Println(s)
for i:=0; i<10000; i++ {
//n:=rand.Int()%100
s=append(s,155)
fmt.Print(len(s),cap(s),": ");
fmt.Println(time.Now().UnixNano()-now)
now = time.Now().UnixNano()
}
}
```
### Esercizio 1 (`fattoriale.go`)
Scrivere un programma che, preso un intero positivo in input da linea di comando, ne restituisce il fattoriale attraverso una funzione ricorsiva.
##### Esempio di esecuizione
```console
$ ./fattoriale 5
120
```
### Soluzione 1
```go
package main
import (
"fmt"
"os"
"strconv"
)
func factorial(n int) int {
if n==0||n==1 {
return 1
}
return (n*factorial(n-1))
}
func main() {
n,err:=strconv.Atoi(os.Args[1])
if err!=nil {
fmt.Println("inserisci un intero!")
os.Exit(0)
}
fmt.Println(factorial(n))
}
```
### Soluzione 2 (parzialmente corretta)
```go
package main
import "fmt"
func fattoriale(num int) int {
if num <= 1 { // idea parzialmente buona per non andare in loop
return num
}
return num * fattoriale(num-1)
}
func main() {
var num int
fmt.Println("inserisci num")
fmt.Scan(&num)
fmt.Println("fattoriale: ", fattoriale(num))
}
```
Il problema qui è che se gli passo `0` come input, come riusltato ottengo `0`, ma `0! = 1`. Però con l'`if` mi evito di entrare in loop con i numeri negativi. Ovviamente se in input ho un numero negativo, in output non ho il suo fattoriale.
### Soluzione 3 (stramba in senso negativo)
```go
package main
import "fmt"
func fact(n int) int {
//for i:=0;i<n;i++{ // inutile (non lo completa mai)
fmt.Println("pre if: ",n);
if n==1{
fmt.Println("=1",n);
return n
} else{
fmt.Println("!=1",n);
return n*fact(n-1)
}
//}
return n
}
func main(){
var n int
fmt.Scan(&n)
res:=fact(n)
fmt.Println(res)
}
```
(già commentate via le righe inutili, per cui torna una soluzione normale)
### Esercizio 2 (`palindromo.go`)
Scrivere un programma che, preso come input un file contenente un testo, verifica se questo sia palindromo.
Mi raccomando ragionate bene sull'assunzione ricorsiva e sul controllo che dovete fare per terminare la ricorsione.
*Suggerimento* prima di risolvere l'esercizio con un testo completo, provate a risolverlo quando il testo contiene una sola parola.
##### Esempio di esecuizione
```shell
$ ./palindromo input_palindromo.txt
si
```
dove `input_palindromo.txt` è, per esempio:
```
Da ore Simone rasa mare.
È capace e va!
Nauta laido,
a ira leggeri ami meri sollevi là!
E là è Dio! Suol ridarti amore!
Pietro con Gesù segnò cortei.
Però mai tradirlo! (uso ideale!)
A livello sì remi:
mai regge l’aria; odia la tua nave!
E capace era, ma s’arenò! Misero!
Ad
```
Notare che i segni di punteggiatura sono da ignorare, come anche gli accenti sulle parole.
```shell
$ ./palindromo input_nonPalindromo.txt
no
```
dove `input_nonPalindromo.txt` è, per esempio:
```
Questa frase non e' palindroma
```
package main
import (
"fmt"
"reflect"
)
func main() {
var s []int
//s=[]int{}
fmt.Println(s, len(s), cap(s), reflect.TypeOf(s))
if s == nil {
fmt.Println("nil!")
}
}
package main
import "fmt"
func main() {
// Create an empty slice of slices.
animals := [][]string{}
// Create three string slices.
row1 := []string{"fish", "shark", "eel"}
row2 := []string{"bird"}
row3 := []string{"lizard", "salamander"}
// Append string slices to outer slice.
animals = append(animals, row1)
animals = append(animals, row2)
animals = append(animals, row3)
// Loop over slices in animals.
for i := range animals {
fmt.Printf("Row: %v\n", i)
fmt.Println(animals[i])
}
}
//scrivere un programma che appenda elementi ad una slice, e che stampi a distanza di un intervallo di tempo
//i vari valori che la slice assume nel tempo
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
var s []int
now := time.Now().UnixNano()
rand.Seed(now)
//d,_=time.ParseDuration("1.5s")
//fmt.Println(s)
for i:=0; i<10000; i++ {
//n:=rand.Int()%100
s=append(s,155)
fmt.Print(len(s),cap(s),": ");
fmt.Println(time.Now().UnixNano()-now)
now = time.Now().UnixNano()
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment