
---------------------------------------------------------------------
Il tema che accomuna i primi programmi e script 
è il calcolo di fattoriali di numeri molto grandi
usando il trucco di calcolarne direttamente il logaritmo,
facendo uso delle ben note proprietà dei logaritmi.
In effetti il linguaggio R possiete già nell'installazione base
la funzione lfactorial() che adempie a questo compito. 
Ad esempio si diano i seguenti comandi R:
  factorial(100)
  lfactorial(100)
  factorial(1000)
  lfactorial(1000)
Come si vede, factorial() non è in grado di calcolare il
fattoriale di 1000 e come risultato dà 'Inf', mentre
lfactorial() fa bene il suo mestiere anche per numeri ben più grandi.

---------------------------------------------------------------------

1. Scrivere uno script R per verificare il massimo numero intero
   del quale la funzione factorial() è in grado di calcolare
   il fattoriale. Ovvero, usando il metodo preferito, si
   esegua un loop sui numeri interi il quale si interrompa
   la prima volta che factorial() 'ritorna' Inf.
   Quando invece il risultato è 'buono' si stampi il numero
   e, in formato esponenziale ('notazione scientifica'),
   il suo fattoriale.

   Inoltre, in fondo allo script si scriva, come commento,
   l'ultimo n per il quale factorial() ha dato un risultato 'sensato'.

   [ nome dello script: fattoriali.R ]


2. Scrivere una funzione C la quale ritorni come 'double'
   il fattoriale di un intero ricevuto come argomento.
   La funzione va chiamata da un main() il quale prende
   l'intero di cui calcolare il fattoriale da riga di comando,
   chiama la funzione e stampa il risultato.
   
   (Nota: nel file del programma va scritto possibilmente prima il main
    e poi la funzione; se si fa il contrario si perdono punticini.
    Prima della funzione mettere, opportunamente commentata
    una sequenza di trattini per separarla dalla precedente -- questa
    accortezza è importante soprattutto quando si hanno diverse funzioni.)

   [ nome del programma: fattoriale.c ]
   [ comando di esecuzione (ad es. per 4!): ./fattoriale 4 ]
   
   NOTA (VALIDA IN GENERALE): si raccomanda di cominciare
        a scrivere il programma a partire da un main 'minimalista'
	e di provarlo, mediante compilazione/esecuzione a ogni passo.

3. Scrivere ora un programma il quale, in analogia con quanto fatto
   nel primo punto, verifichi il massimo fattoriale ottenibile con double.
   Per fare questo si copi fattoriale.c in test_fattoriale.c e si
   modifichi quest'ultimo nel seguente modo:
   - il main questa volta prende, sempre da riga di comando,
     il massimo intero (nmax) del quale si vuol fare il fattoriale;
   - esegue quindi un loop da 1 a nmax, stampando ad ogni ciclo
     il numero e il fattoriale ottenuto;
   - il loop si interrompe con la condizione di 'infinito', mediante
     il confronto con DBL_MAX definita in float.h

   [ nome del programma: test_fattoriale.c ]
   

4. A questo punto scrivere finalmente la funzione lfactorial()
   che calcola il logaritmo del fattoriale (si raccomanda di copiare
   e modificare opportunamente il file fattoriale.c).
   Come al solito, il main prende l'intero di cui calcolare il
   log del fattoriale e chiama lfactorial(), quindi stampa:
   a) il logaritmo del fattoriale;
   b) il fattoriale in notazione scientifica, elaborando opportunamente
      il risultato ottenuto per estrarre mantissa e potenza di 10.
   (Ovviamente, al fine di controllare la correttezza del risultato
    si confronti, per alcuni interi, quanto ottenuto da questo programma
    con quanto si ottiene dal programma del punto 2 e dalle funzioni di R.

    [ nome del programma: lfattorial.c ]
    [ comando di esecuzione (ad es. per 1000!): ./fattoriale 1000 ]
      -> la stampa del punto b) deve dare  "1000! = 4.02387e+2567"


--------------------------------------------------------------------------
La seconda parte consiste nel generare e analizzare lanci simulati
di dadi.
--------------------------------------------------------------------------

5. Per prima cosa scriviamo le funzioni di interesse e il
   main per testarle
   - Scrivere la funzione 'dado' la quale a ogni chiamata
     ritorna in modo equiprobabile un intero fra 1 e 6.
   - Scrivere quindi la funzione 'dadi', con argomento
     il numero di dadi 'n' da lanciare, la quale chiama n volte
     la funzione dado e ritorna la somma dei numeri ottenuti
     in ciascun 'lancio'.
   - Scrivere quindi il main, il quale prenda da riga di comando
     il numero di dadi da lanciare, chiami la funzione 'dadi'
     e stampi il valore ottenuto.
   - Per quanto riguarda l'inizializzazione del generatore
     di numeri casuali, in questo caso conviene usare
     l'orologio interno del computer, al fine di ottenere
     numeri diversi a ogni lancio. Viene data direttamente
     la funzione nel file inizializza_random.c, la quale va inserita
     nel file he stiamo scrivendo, insieme agli header necessari.
   (Anche se questo è l'ordine logico, si raccomanda di cominciare
   sempre dal main e compilare/eseguire a mano a mano si va avanti
   nella scrittura del programma.)

    [ nome del programma: lancia_dadi.c ]
    [ comando di esecuzione (ad es. per 2 dadi): ./lancia_dadi 2 ]

6. Una volta confidenti che il lancio di n dadi dia risultati
   ragionevoli, generiamo lunghe sequenze di lanci, di ciascuna
   di esse effettuiamo una statistica riassuntiva e scriviamo i
   "riassunti statistici" in un file di tipo testo
   da rileggere successivamente da R per ulteriori analisi.
   Operativamente:
   - definire la costante NLANCI, che porremo pari a 100000
     (ma nella fase iniziale di 'debug' con delle stampe
     è conveniente usare un numero piccolo);
   - definire nel main un array unidimensionale ('vettore')
     di interi in grado di contenere la sequenza generata;
   - definire inoltre il vettore 'ndadi' che contiene i valori
     interi 1, 2, 5, 10, 20, 50 e 100: essi saranno il numero di dadi
     che 'lanceremo contemporaneamente';
   - rimuovere dal main la parte iniziale in quanto questo
     programma verrà lanciato senza parametri a riga di comando;
   - per quanto riguarda l'inizializzazione della random,
     in questo caso è preferibile avere sequenze ripetibili e
     quindi la random va inizializzata usando il proprio numero
     di matricola;
   - eseguire un loop sulle sette possibilità di ndadi[] e,
     per ciascuna di esse,
     - riempire il vettore di dimensione NLANCI che contiene la sequenza
       delle somme ottenute;
     - passare tale vettore a una funzione che esegua dei 'summaries'
       statistici sulla sequenza (vedi dopo) la quale calcola
       la media e la deviazione standard dei valori della sequenza;
     - scrivere su un file una riga contenente, nell'ordine,
       il numero di dadi, la lunghezza della sequenza (che è sempre
       la stessa, ma potrebbe far comodo in generale), la media
       e la deviazione standard.
       (Ovviamente il file deve essere stato aperto precedentemente
        e chiuso alla fine).

    La funzione che fa la statistica deve essere di tipo 'void'
    e deve essere in grado di 'ritornare in modo opportuno'
    i due valori statistici.
    Si ricorda inoltre che la deviazione standard ('campionaria')
    si ottiene facendo la radice quadrata della varianza ('campionaria')
    la quale si calcola a sua volta facendo la
    "media dei quadrati dei valori meno il quadrato della media dei valori"
    (e senza preoccuparsi del famigerato "n-1" di cui qualcuno
     potrebbe aver sentito parlare!)

    [ nome del programma:     sequenze_dadi.c   ]
    [ nome del file dei dadi: sequenze_dadi.txt ]

7. Terminiamo rileggendo da uno script R il file sequenze_dadi.txt
   ed effettuando ulteriori analisi.
   - innanzitutto importare il contenuto di sequenze_dadi.txt
   - plottare quindi (su due plot separati),
     la media e la  deviazione standard in funzione del
     numero di dadi lanciati simultaneamente e 
     mettendo possibilmente sul plot delle 'label'
     che aiutino a capire meglio il significato dei punti.
     [ Fra un plot e l'altro effettuare una pausa
     mediante una chiamata a readline() con un 'prompt' che inviti
     a premere un tasto per continuare (senza leggere niente).]
     
     Il primo plot sarà alquanto banale e quindi ci concentreremo
     solo sul secondo.
   - Linearizzare l'andamento in modo da capire la legge 'empirica'
     (facciamo finta di non conoscere le leggi della statistica)
     che lega la deviazione standard al numero di dadi lanciati
     simultaneamente:
     -> plot linearizzato;
     -> valutazione dei coefficienti della legge empirica
        (senza tante elugubrazioni statistiche, per quello che ci interessa,
	utilizzato semplicemente il primo e l'ultimo punto):
     -> sovrimporre infine sul plot l'andamento empirico trovato

     [ nome dello script: sequenze_dadi.R ]
