---
title: "Programmazione"
author: "Stefano Bussolon"
date: "03/2019 - 01/2020"
output:
  xaringan::moon_reader:
    lib_dir: libs
    nature:
      highlightStyle: github
      highlightLines: true
      countIncrementalSlides: false

---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, comment = NA)
```

# Programmazione

---

Nelle lezioni precedenti abbiamo utilizzato R come un ambiente statistico a linea di comando, dove far *girare* degli script, invocando delle funzioni.

In questa lezione ci focalizzeremo sulla creazione di funzioni.

---

## Ciao

Iniziamo con un esempio molto semplice: la creazione della funzione `ciao()`, il cui scopo è quello di salutare.

```{r prog_ciao}
ciao <- function() {
	messaggio <- "ciao a tutti"
	return (messaggio)
}

```

Invochiamo la funzione

```{r prog_ciao_call}

ciao()

```

---

### Passaggio di un argomento

La versione seguente richiede un parametro (un nome) che verrà usato per personalizzare il saluto

```{r prog_ciaoNome}
ciaoNome <- function (nome) {
	messaggio <- paste("ciao ", nome, ", come stai?", sep="" )
	return (messaggio)
}

```

Se invochiamo la funzione senza il parametro, R segnalerà un errore.

```{r prog_ciaoNome_i}
ciaoNome("Francesco")
# ciaoNome() # il parametro è obbligatorio
```

---

### Valore di default

In questa iterazione, assegnamo al parametro `nome` un valore di default, che verrà usato se, nell'invocazione, non verrà specificato alcun valore.

```{r prog_ciaoNomeAmico}

ciaoNomeAmico <- function (nome="amico") {
	messaggio <- paste("ciao ", nome, ", come stai?", sep="" )
	return (messaggio)
}

```

```{r prog_ciaoNomeAmico_i}

ciaoNomeAmico("Marika")
ciaoNomeAmico()
```

---

### If

In questa iterazione gestiamo la presenza o meno del parametro nell'invocazione.  
Se il parametro non c'è, salutiamo l'anonimo.

```{r prog_ciaoNomeForse}

ciaoNomeForse <- function (nome=NULL) {
	messaggio <- ""
	if(!is.null(nome)) {
		messaggio <- paste("ciao ", nome, ", come stai?", sep="" )
	} else {
		messaggio <- "Ciao anonimo ;)"
	}
	return (messaggio)
}

```


```{r prog_ciaoNomeForse_i}
ciaoNomeForse("Matteo")
ciaoNomeForse()

```

---

### For

In questa iterazione, gestiamo un vettore di più nomi, introducendo il ciclo `for`.

```{r prog_ciaoNomi}
ciaoNomi <- function (nomi=c()) { # c() vettore vuoto
	messaggio <- "ciao "
	for (nome in nomi) {
		messaggio <- paste(messaggio, nome, ", ", sep="")
	}
	messaggio <- paste(messaggio, "come state?", sep="")
	return (messaggio)
}

```

---

```{r prog_ciaoNomi_i}
nomi <- c("Mario", "Antonella", "Lucia")
ciaoNomi(nomi)
ciaoNomi()

```

---

### If, else, for

Una versione più complessa, che gestisce un parametro (con valore di default, ovvero il vettore vuoto), e 4 diversi scenari: vettore vuoto, vettore con un solo valore, vettore con meno di 4 valori (di fatto 2 o 3 nomi), vettore con almeno 4 valori.

---

```{r prog_ciaoDipende}
ciaoDipende <- function (nomi=c()) { # c() vettore vuoto
	if (length(nomi)==0) {
		return ("ciao anonimo, come stai? Sei timido?")
	}
	if (length(nomi)==1) {
		messaggio <- paste ("ciao ", nomi[1], ", come stai?", 
												sep="")
		return (messaggio)
	}
	messaggio <- "ciao "
	if (length(nomi)<4) {
		for (nome in nomi) {
			messaggio <- paste(messaggio, nome, ", ", sep="")
		}
	} else {
		messaggio <- paste(messaggio, "a tutti, ", sep="")
	}
	messaggio <- paste(messaggio, "come state?", sep="")
	return (messaggio)
}
```

---

```{r prog_ciaoDipende_i}

ciaoDipende(c("Giovanna", "Barbara"))
ciaoDipende(c("Giovanna", "Barbara", 
							"Enrico", "Tommaso", "Gianluca"))
ciaoDipende()
ciaoDipende("Enrico")

```

---

## Funzioni

```{r eval=FALSE}

nomeFunzione <- function (argomento1, argomento2=default) {
	# corpo della funzione
	return(valore) # valore da sostituire
	
}

```

---

## Funzione, corpo, argomenti

```{r}

# il corpo della funzione
body(ciaoNomi)

# gli argomenti della funzione
formals(ciaoNomi)

```


---

## If

```{r eval=FALSE}

if (condizioneLogica) {
	# se la condizione è vera,
	# esegui il codice fra le parentesi
} else if (secondaCondizione) { # facoltativo
	# se la prima è falsa ma la seconda è vera
	# esegui la seconda
} else { # facoltativo
	# se le condizioni precedenti sono tutte false,
	# esegui invece questo codice
}

```

---

## For

```{r eval=FALSE}

for (elemento in vettore) { # o sequenza
	# esegui questo codice
	# per ognuno degli elementi 
}

```


---

## Altre strutture di controllo

*while*: esegue un loop finché la condizione è vera

*break*: interrompe un loop (for, while, repeat)

*repeat*: loop infinito (è necessario interromperlo con un break)

*next*: passa alla iterazione successiva del loop


---

## Esercizi

---

### La media

Creare la funzione `media(vettore)` senza usare le funzioni `mean()` e `sum()`.

```{r prog_laMedia, echo=FALSE}

media <- function (vettore) {
	somma <- 0
	for (valore in vettore) {
		somma <- somma + valore
	}
	laMedia <- somma / length(vettore)
	return(laMedia)
	
}

```

Test: 

```{r prog_laMedia_test}

vettore1 <- sample(1:10,20, replace = TRUE)
media(vettore1)
mean(vettore1)

```

---

### Selezione

Creare la funzione `seleziona(vettore, filtro)` senza usare il selettore `vettore[filtro]`.


```{r echo=FALSE}

seleziona <- function(vettore, filtro) {
	ritorno <- c()
	for (i in 1:length(vettore)) {
		if (filtro[i]== TRUE)
			ritorno <- c(ritorno,vettore[i])
	}
	return (ritorno)
}

```

Test

```{r}
vettore2 <- seq(10)
vFiltro <- c(TRUE,FALSE,TRUE,FALSE,FALSE,
						FALSE,TRUE,TRUE,FALSE,FALSE)
vettore2[vFiltro]
seleziona(vettore2,vFiltro)

```

---

### Sequenza

Creare la funzione `sequenza(inizio,fine)` senza usare la funzione `seq()` né `inizio:fine`.


```{r echo=FALSE}

sequenza <- function (inizio, fine) {
	conta <- inizio
	ritorno <- c()
	while (conta <= fine) {
		ritorno <- c(ritorno,conta)
		conta <- conta + 1
	}
	return (ritorno)
} 

```

Test

```{r}

seq(7,12)

sequenza(7,12)

```



---

### Lancio di dadi

Creare la funzione lancio (numDadi) che simula il lancio di `numDadi` dadi e la somma del loro risultato

```{r prog_lancioDadi, echo=FALSE}

lancio <- function (numDadi = 1) {
	somma <- sum(sample(1:6,numDadi,replace = TRUE))
	return (somma)
}
```

---

Test
```{r prog_lancioDadi_test}
lancio(1)
lancio(1)
lancio(2)
lancio(2)
lancio(3)


```

---

Simulare mille lanci di un dado (salvando i risultati in `lanci1`), e mille lanci di due dadi (salvando i risultati in `lanci2`)

```{r prog_lancio1000Dadi, echo=FALSE}

lanci1 <- rep(0,10000)
for (i in 1:length(lanci1)) {
	lanci1[i] <- lancio(1)
	#print(lanci1[i])
}

lanci2 <- rep(0,10000)
for (i in 1:length(lanci2)) {
	lanci2[i] <- lancio(2)
	#print(lanci1[i])
}

```

--

Creare un file in rMarkdown (es dadi.Rmd), inserire i chunk relativi alla funzione dati e allo script dei lanci, con una breve descrizione dei due passaggi.

--

Usando ggplot2, mostrare gli istogrammi dei due vettori `lanci1` e `lanci2` ed aggiungerli al file rMarkdown.

---

```{r cowplot, echo=FALSE, warning=FALSE}
library(ggplot2)
library(cowplot)

```


```{r prog_lanci_his, echo=FALSE, warning=FALSE}

farlocco <- data.frame(lanci1,lanci2)

library(ggplot2)

histLanci1 <- ggplot(data=farlocco,aes(lanci1)) + 
	geom_histogram(bins = 6) +
	labs(title="",
			 x="",
			 y="",
			 subtitle="", 
			 caption="")

#plot(histLanci1)

histLanci2 <- ggplot(data=farlocco,aes(lanci2)) + 
	geom_histogram(bins = 11) +
	#geom_density() +
	labs(title="",
			 x="",
			 y="",
			 subtitle="", 
			 caption="")

#plot(histLanci2)
plot_grid(histLanci1, histLanci2, labels = c("1 dado", "2 dadi"), ncol = 2, align = "v")

```
---

Creare la funzione `minmax` che restituisce un vettore con i valori minimo e massimo di un vettore, senza usare `min` e `max`


```{r prog_minmax, echo=FALSE, warning=FALSE}

minmax <- function (vettore) {
	risultato <- c()
	if (length(vettore)<1) {return (risultato)}
	minimo <- vettore[1]
	massimo <- vettore[1]
	for (i in 1:length(vettore)) {
		if (vettore[i]< minimo) {
			minimo = vettore[i]
		}
		if (vettore[i]> massimo) {
			massimo = vettore[i]
		}
	}
	risultato <- c(minimo,massimo)
	return (risultato)
}

```

```{r prog_minmax_test}

vettore3 <- sample(1:1000,20,TRUE)

min(vettore3)
max(vettore3)
minmax(vettore3)

```

---

### Rovesciare un vettore

Creare la funzione `gira` che, dato un vettore, lo gira, senza usare la funzione `rev()`.

```{r prog_gira, echo=FALSE, warning=FALSE}


gira <- function (vettore) {
	risultato <- c()
	if (length(vettore)<1) {return (risultato)}
	posizione <- length(vettore)
	while (posizione >0){
		risultato <- c(risultato,vettore[posizione])
		posizione <- posizione -1
	}
	return (risultato)
}



```


```{r prog_gira_test}

vettore4 <- sample(1:100,10,TRUE)

vettore4
rev(vettore4)
gira(vettore4)

```
---

### Riprodurre la funzione any

Creare la funzione `tutti(vettore)` la funzione `all()` senza, ovviamente, usare la funzione `all()`

```{r prog_any, echo=FALSE, warning=FALSE}

tutti <- function (vettore) {
	if (length(vettore)<1) {return (NULL)}
	risposta <- TRUE
	for (i in length(vettore)) {
		if(vettore[i]==FALSE) return (FALSE)
	}
	return (TRUE)
}

```

```{r prog_any_test1}

(vero <- rep(TRUE,5))
all(vero)
tutti(vero)
```
---

```{r prog_any_test2}

(misto <- sample(c(TRUE,FALSE),5,replace = TRUE))
all(misto)
tutti(misto)

```

