esercizi 28/11/2019

parent 09ddfcb2
# Esercizi 28 novembre 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
## Esercizio 1 (``ribaltaArray.go``)
Scrivere un programma che alloca un array di dimensione random e con contenuto random attraverso una funzione, lo stampa e poi (attraverso una funzione creata ad hoc) lo "ribalta" (la prima posizione diventa l'ultima ecc.)
Esempio: ``[1,2,3,4]`` diventa ``[4,3,2,1]``
*Note*:
* è necessario passare un puntatore come parametro della funzione che ribalta l'array
* NON si deve creare un secondo array
* Non è possibile dichiarare un array nel seguente modo... usate il comando ``make``
```go
lung := 2
var a [lung]string
//Errore: ./prog.go: non-constant array bound lung
```
### Soluzione parziale 1
Sbagliata, perchè nella funzione l'array viene passato per copia e non per riferimento
```go
package main
import (
"fmt"
)
// La Parte Random La Sto Ancora Facendo
func ribaltaArray(array [5]int) [5]int{
for i:=0; i<(len(array)/2); i++{
array[i], array[len(array)-i-1] = array[len(array)-i-1], array[i]
}
return array
}
// ---------------------------------------------------
func main(){
var arreih [5]int
arreih = [5]int {1,2,3,4,5}
fmt.Println(ribaltaArray(arreih))
}
```
mi aspettavo:
```go
func main(){
var arreih [5]int
arreih = [5]int {1,2,3,4,5}
fmt.Println(arreih)
ribaltaArray(arreih)
fmt.Println(arreih)
}
```
### Soluzione 2
```go
package main
import (
"fmt"
"math/rand"
"time"
)
func init () {
rand.Seed(time.Now().UTC().UnixNano())
}
func makeArray (a []int) {
for i := 0; i < len(a); i++ {
a[i] = rand.Int() % 1000
}
}
func ribaltarray (a []int) {
for i := 0; i < len(a) / 2; i++ {
a[i], a[len(a) - 1 - i] = a[len(a) - 1 - i], a[i]
}
}
func main () {
var l int
l = rand.Int() % 20
var a []int
a = make ([]int, l)
fmt.Println(a)
makeArray(a)
fmt.Println(a)
ribaltarray(a)
fmt.Println(a)
}
```
## Esercizio 2 (``tartaruga.go``)
Viene fornito il seguente codice:
```go
type Turtle struct {
x, y int
direction Direction
}
type Direction int
const (
Nord Direction = iota
Est
Sud
Ovest
)
```
che descrive una tartaruga fornendone la posizione (x,y) in un ipotetico piano cartesiano e la direzione (direction) verso cui si sta muovendo.
Il vostro compito è quello di implementare le seguenti funzioni:
``status`` : stampa l'attuale posizione della tartaruga e la sua direzione
``forward`` : che "muove" virtualmente la tartaruga di un certo numero di "passi" tenendo conto dell'attuale direzione
``backward`` : che fa arretrare la tartaruga
``right`` : ruota la direzione della tartaruga di 90° verso destra
``left`` : ruota la direzione della tartaruga di 90° verso sinistra
Testare ogni metodo implementato in un main
*Nota* se non sapete cosa sia ``iota`` : https://golang.org/ref/spec#Iota
### Soluzione 1 (corretta)
```go
package main
import (
"fmt"
)
type Turtle struct {
x, y int
direction Direction
}
type Direction int
const (
Nord Direction = iota
Est
Sud
Ovest
)
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])
}
func forward (t *Turtle, steps int) {
switch (*t).direction {
case Nord:
(*t).y+=steps
case Est:
(*t).x+=steps
case Sud:
(*t).y-=steps
case Ovest:
(*t).x-=steps
}
}
func backward (t *Turtle, steps int) {
switch (*t).direction {
case Nord:
(*t).y-=steps
case Est:
(*t).x-=steps
case Sud:
(*t).y+=steps
case Ovest:
(*t).x+=steps
}
}
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
var steps int
i:=1
for i>0 {
fmt.Print("1. Avanti\n2. Indietro\n3. Ruota a destra\n4. Ruota a sinistra\n5. Stampa status\n0. Esci\n")
fmt.Scan(&i)
switch i {
case 1:
fmt.Print("Numero di passi: ")
fmt.Scan(&steps)
forward(&t, steps)
case 2:
fmt.Print("Numero di passi: ")
fmt.Scan(&steps)
backward(&t, steps)
case 3:
right(&t)
case 4:
left(&t)
case 5:
status(&t)
}
}
}
```
## Estensione 1 ``tartaruga.go``
Immaginate che la tartaruga si stia muovendo all'interno di uno spazio definito, e non più all'interno di un piano cartesiano.
Ad esempio, supponiamo che la tartaruga si muova in una griglia di *NxM* quadretti.
Adattate le funzioni ``forward`` e ``backward`` in modo che la tartaruga si muova correttamente all'interno dello spazio.
*Nota: se la tartaruga "esce" da un confine, rientra da quello opposto ---un po come snake. In sostanza stiamo definendo un toroide* https://it.wikipedia.org/wiki/Toro_(geometria)
Aggiungete poi una funzione ``stampa`` che stampa la griglia con la tartaruga al suo interno
### Soluzione 1
```go
package main
import (
"fmt"
)
type Turtle struct {
x, y int
direction Direction
}
type Direction int
const (
Nord Direction = iota
Est
Sud
Ovest
)
const (
MaxX int = 30
MaxY int = 10
)
// ⬜️🐢🌱🌿☘️🍀
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 {
fmt.Print("🌱")
}
}
fmt.Println()
}
}
func forward (t *Turtle, steps int) {
switch (*t).direction {
case Nord:
(*t).y=((*t).y+steps)%MaxY
case Est:
(*t).x=((*t).x+steps)%MaxX
case Sud:
(*t).y=((*t).y+MaxY-steps)%MaxY
case Ovest:
(*t).x=((*t).x+MaxX-steps)%MaxX
}
}
func backward (t *Turtle, steps int) {
switch (*t).direction {
case Nord:
(*t).y=((*t).y+MaxY-steps)%MaxY
case Est:
(*t).x=((*t).x+MaxX-steps)%MaxX
case Sud:
(*t).y=((*t).y+steps)%MaxY
case Ovest:
(*t).x=((*t).x+steps)%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
var steps int
i:=1
for i>0 {
fmt.Print("1. Avanti\n2. Indietro\n3. Ruota a destra\n4. Ruota a sinistra\n0. Esci\n")
fmt.Scan(&i)
switch i {
case 1:
fmt.Print("Numero di passi: ")
fmt.Scan(&steps)
forward(&t, steps)
case 2:
fmt.Print("Numero di passi: ")
fmt.Scan(&steps)
backward(&t, steps)
case 3:
right(&t)
case 4:
left(&t)
}
status(&t)
}
}
```
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