Realizziamo adesso un algoritmo con Scratch che controlli se i numeri inseriti in input sono numeri perfetti.
Definizione di numero perfetto
Un numero si dice perfetto quando è uguale alla somma dei divisori propri (tutti i divisori tranne il numero stesso).
Ad esempio il più piccolo numero perfetto è 6 in quanto i suoi divisori escluso se stesso sono 1, 2 e 3.
Procedimento algoritmo sui numeri perfetti con Scratch
Per la risoluzione dell’algoritmo utilizziamo le variabili:
numero che rappresenta il numero da valutare
div che rappresenta il divisore per cui verrà diviso il numero
somma che conterrà la somma dei divisori.
Quindi chiediamo all’utente di inserire un numero e memorizziamo la risposta nella variabile numero.
Dobbiamo trovare i divisori del numero preso in input, sommarli e dopo confrontare la somma ottenuta con il numero.
Quindi dovrei cominciare a dividere i numeri prima per 1, poi per 2, poi per 3, ecc…
Ma è scontato che ciascun numero è divisibile per 1, quindi faccio partire il divisore da 2. Chiamiamo la variabile divisore div e assegniamo a div il valore di 2.
Creo inoltre la variabile somma che conterrà la somma dei divisori.
Farò partire la variabile somma da 1, perché come detto sopra, possiamo già sommare il divisore 1.
All’interno del ciclo controlliamo se il numero è divisibile per div.
Come si fa a controllarlo?
Basterà controllare se il resto della divisione di numero diviso div è uguale a zero.
Se vero allora aggiorno la variabile somma aggiungendo il valore di div, altrimenti non lo aggiungo. In ogni caso vado avanti e incremento div di 1.
Continuo finché il divisore non raggiunge la metà del numero (numero/2) infatti è scontato che dividendo un numero per un numero maggiore della sua metà si avrà un numero con la virgola, ovvero si avrà che il resto è diverso da zero.
Al termine controllo se il numero inserito coincide con la somma.
Se è così il numero è perfetto, altrimenti non lo è.
È chiaro che ci possono essere altre possibili soluzioni o ampliamenti dell’algoritmo stesso. Proponete pure la vostra soluzione nei commenti e ne discuteremo assieme.
Oggi realizzeremo il gioco della morra cinese con Scratch.
Innanzitutto vediamo le regole del gioco
Si gioca in due, gli strumenti sono le mani dei giocatori e ciascun giocatore può scegliere un oggetto: forbice (f), sasso (s) o carta (c).
Sasso, con la mano a pugno;
Carta, con la mano aperta;
Forbici, con soli indice e medio distesi.
Le regole sono queste:
Il sasso batte la forbice (la rompe);
La forbice batte la carta (la taglia);
La carta batte il sasso (lo avvolge).
Se si sceglie la stessa arma il punteggio è pari.
Vince chi raggiunge per primo il punteggio stabilito.
Procedimento del gioco della Morra Cinese con Scratch
Dapprima scegliamo uno sfondo ed uno sprite qualunque, poi facciamo giocare il computer generando una scelta random tra forbice, carta o sasso. Memorizziamo il valore trovato in una variabile che chiameremo computer e dove memorizzeremo un valore random da 1 a 3.
Facciamo in modo che:
se la scelta random ricade sul numero uno corrisponde a sasso;
se la scelta random ricade sul numero due corrisponde a carta;
infine se la scelta random ricade sul numero tre corrisponde a forbice.
Dopo toccherà al giocatore che a caso da tastiera potrà scegliere:
s per sasso;
f per forbice e
c per carta.
Memorizziamo il risultato nella variabile giocatore.
Adesso dobbiamo impostare i vari casi.
Se entrambi giocano lo stesso oggetto sono pari; altrimenti se il giocatore gioca sassoe il computer forbiceoppure se il giocatoregioca forbicee il computer carta oppure ancora se il giocatoregioca cartae il computersasso, il giocatore vince; ovviamente in tutti gli altri casi il giocatore perde.
Allego lo script di esempio:
Potremmo anche più semplicemente controllare che la variabile computer sia uguale a giocatore per la parità! Occorre però cambiare le assegnazioni di computer ad s, f e c.
Si può creare anche un ciclo per generare più giocate e quindi stabilire un punteggio.
Ovviamente ci possono essere tante altre soluzioni al gioco della morra cinese realizzato con Scratch, proponete pure la vostra nei commenti sotto.
Realizziamo un programma che risolva un’equazione di secondo grado in C.
Equazioni di secondo grado
Innanzitutto partiamo dalla definizione. Un’equazione di secondo grado è un’equazione di grado 2 con, eventualmente, esponenti di grado inferiore.
Un’equazione di secondo grado scritta nella forma canonica è del tipo:
ax2+bx+c=0
Dove
a è il coefficiente del termine di grado 2
b è il coefficiente del termine di grado 1
c è il coefficiente del termine di grado 0, detto anche termine noto
Per risolvere l’equazione occorre conoscere i tre coefficienti. Una volta acquisiti i tre valori occorre calcolare il determinante o delta utilizzando la formula:
b*b-4*a*c;
In base al determinante si verificano queste situazioni:
se il determinante è minore di zero, non esistono soluzioni reali;
se il determinante è uguale a zero, l’equazione ammette due soluzioni reali coincidenti;
se il determinante è maggiore di zero, l’equazione ammette due soluzioni reali distinte;
Inoltre, se il coefficiente a è uguale a zero, chiaramente non ci troveremo più di fronte ad un’equazione di secondo grado ma di primo grado. Dunque ovviamente non si potrà applicare la formula.
Nei casi in cui le soluzioni esistono si ottengono con questa formula:
x1=(-b+sqrt(determinante))/2*a
x2=(-b-sqrt(determinante))/2*a
dove sqrt è la funzione per il calcolo della radice quadrata.
Procedimento dell’algoritmo per la risoluzione delle equazioni di secondo grado
Per risolvere le equazioni di secondo grado in C, si possono creare tante soluzioni.
Ve ne propongo due, una con l’uso delle funzioni o procedure e l’altra senza.
Esempio 1: equazione di secondo grado senza funzioni create in C
Oggi parleremo delle funzioni in C, uno strumento molto utile e potente che consente il riutilizzo di blocchi di istruzione.
Una funzione può essere vista come un sottoprogramma dove vengono aggregati gruppi di istruzioni.
Le funzioni in C sono utilizzate proprio per evitare di replicare porzioni di codice; infatti invocare un sottoprogramma vuol dire mandare in esecuzione la porzione di codice ad esso relativa.
Una funzione può essere invocata anche più volte e chiaramente in tal caso la porzione di codice verrà ripetuta tante volte quante sono le invocazioni.
In definitiva ogni funzione prende in ingresso un insieme di argomenti detti parametri e restituisce un valore.
Fino ad ora abbiamo utilizzato la funzione main(), che come abbiamo già detto, è la funzione che rappresenta il corpo del programma in C.
Differenza tra procedure e funzioni in C
Innanzitutto occorre fare una distinzione tra procedure e funzioni. Le funzioni in C ritornano un valore, se il valore di ritorno non è specificato, si assume per default int; se la funzione non ritorna alcun valore, allora si usa un ‘tipo speciale’ detto void, in questo caso parliamo di procedure.
La differenza sostanziale tra funzioni e procedure è dunque che le funzioni restituiscono un qualcosa mentre le procedure no.
Dichiarazioni di funzioni e procedure in C
Prima di utilizzare una funzione occorre dichiararla come si fa per le variabili. Ma, a differenza di quanto abbiamo visto per le variabili, non è sempre necessario dichiarare una funzione prima di poterla invocare.
La dichiarazione ci permette di capire unicamente come invocarla, ma non è obbligatoria. Essa infatti specifica quali e quanti argomenti prende in input, oltre al tipo del valore di ritorno.
La dichiarazione, detta anche prototipo della funzione, và fatta prima del main().
<tipo_ritorno> è il valore di ritorno specificato, ricordiamo che se non viene specificato si assume per default int e se il tipo di ritorno è void si tratta di una procedura.
nome_funzione o nome_procedura è il nome che viene dato alla funzione o alla procedura. Si raccomanda di dare nomi sensati e di seguire le stesse regole sintattiche che si utilizzano per le variabili.
elenco_parametri rappresentano i valori in ingresso su cui agire, detti anche parametri formali.
Ecco quindi alcuni esempi di dichiarazione:
double cubo(float c);
int max(int x, int y);
int minimo(double x, y);
che equivale a: int minimo(double a, int b); e non a: int minimo(double a, double b);
int fattoriale(int);
void stampa(); indica la dichiarazione della procedura stampa();
Una dichiarazione inoltre deve essere coerente con la definizione che la segue.
Definizione di funzioni e procedure in C
Prima di essere utilizzata una funzione deve essere o dichiarata o definita.
Una funzione viene definita o prima del main()se non è presente ladichiarazione, altrimenti può essere definita anche dopo il main().
Se il compilatore ad esempio trova una chiamata alla funzione prima della sua definizione, non sa quanti e di che tipo siano i parametri, quindi fa delle assunzioni e magari effettua dei casting, ma non sempre in maniera corretta.
Le funzioni in C ritornano un valore specificato e si definiscono in questo modo:
per <tipo_ritorno>, nome_funzione o nome_procedura ed elenco_parametri valgono le stesse regole di prima.
Quindi tra le parentesi graffe si inseriscono le istruzioni e tra queste istruzioni assume particolare importanza return, che viene utilizzata per restituire un valore al chiamante. Il valore restituito però deve essere compatibile con il tipo restituito dalla funzione.
Facciamo dunque alcuni esempi.
Funzione che prende due interi e restituisce l’intero più grande:
int max(int x, int y)
{
if (x >= y)
return x;
else return y;
}
Esempio dove si verifica una conversione implicita. Si verifica quando il valore restituito non è coerente con il tipo_ritorno. In questo caso, infatti, la funzione PiGreco ritornerà il valore troncato a 3.
int PiGreco()
{
return 3.14;
}
Dunque, se non c’è coerenza tra il tipo di ritorno e il tipo dell’espressione passata a return, si applicano le regole di conversione implicita.
Quindi in definitiva o la dichiarazione (prototipo) o la definizione devono sempre precedere ogni utilizzo della funzione stessa.
N.B. Una funzione si può dichiarare all’interno di un’altra funzione, ma non si può definire. Dunque in C non si possono definire funzioni dentro funzioni.
Invocazione di una funzione o procedura in C
L’invocazione, ovvero la chiamata di funzione, è un’istruzione che permette l’esecuzione della funzione.
Esempi:
c=cubo(lato); viene invocata la funzione cubo su lato;
b=quadrato(x); viene invocata la funzione quadrato su x;
max=massimo(x,y); viene invocata la funzione massimo sui numeri x e y.
Facciamo adesso degli esempi molto semplici per capire meglio l’uso delle funzioni.
Esempio 1 di funzioni in C – funzione che calcola il volume di un cubo
Per quanto detto prima, per poter utilizzare un identificatore occorre dichiararlo, quindi inserisco:
double cubo(float); //dichiarazione o prototipo di funzione
In questo modo dichiaro la funzione cubo, prima del main(), che restituisce al programma un valore di tipo double e si dichiara che accetta in ingresso un solo argomento il cui tipo è float. Quindi in questo caso la definizione della funzione può avvenire anche dopo l’invocazione.
double cubo(float c) //definizione di funzione { return c*c*c; }
In alternativa, se ometto la dichiarazione, allora devo inserire la definizione della funzione prima del main().
Allego i due esempi. Il primo con la dichiarazione della funzione o prototipo:
#include <stdio.h>
double cubo(float);//prototipo o dichiarazione della funzione
main () {
float lato;
double c;
printf("Inserisci il lato del cubo, calcolero' il volume:\n");
scanf("%f", &lato);
c=cubo(lato); //invocazione della funzione
printf("%.2f", c);
}
double cubo(float c) //definizione della funzione
{
return c*c*c;
}
Seconda soluzione senza dichiarazione ma con la definizione
#include <stdio.h>
double cubo(float c) //definizione funzione cubo
{
return c*c*c;
}
main ()
{
float lato;
double c;
printf("Inserisci il lato del cubo, calcolero' il volume:\n");
scanf("%f", &lato);
c=cubo(lato); //invocazione funzione cubo
printf("%.2f", c);
}
Esempio 2 di procedura in C – visualizzare un messaggio
Un tipico esempio di procedure, ovvero di funzioni che non ritornano nessun valore, è quando dobbiamo visualizzare semplicemente un messaggio. Quindi un esempio banale è questo:
#include <stdio.h>
double cubo(float c) //definizione di funzione
{
return c*c*c;
}
void stampa() //definizione di procedura
{
printf("Il volume e':\t");
}
main ()
{
float lato;
double c;
printf("Inserisci il lato del cubo, calcolero' il volume:\n");
scanf("%f", &lato);
c=cubo(lato); //invocazione di funzione
stampa(); //invocazione di procedura
printf("%.2f", c);
}
Esempio 3 – conto alla rovescia con le procedure
Facciamo un altro semplicissimo esempio sull’uso delle procedure. Realizzeremo quindi un programma che fa il conto alla rovescia utilizzando una procedura.
#include <stdio.h>
void contare(int j) //definizione di procedura
{
printf("%d\t", j);
}
int main() {
int i;
for (i=10; i>0; i--)
contare(i); //invocazione procedura
return 0;
}
Esempio 4 – uso delle funzioni per il calcolo del massimo fra 3 numeri
Facciamo adesso un altro semplice esempio che calcola il massimo tra 3 numeri, stavolta utilizzando le funzioni.
#include <stdio.h>
int massimo(int x, int y, int z)
{
int max=x;
if (y>max) max=y;
if (z>max) max=z;
return max;
}
int main() {
int a, b, c;
printf("dammi 3 numeri:\n");
scanf("%d %d %d",&a,&b,&c);
printf("il massimo e': %d", massimo(a,b,c));
return 0;
}
Esempio 5 – media di 10 numeri usando una funzione
Supponiamo di voler fare la media dei voti di 10 materie e utilizziamo una funzione somma che poi invocheremo per fare la media.
Realizziamo oggi un esempio sulle funzioni in C++, al fine di consolidarne l’uso.
Consideriamo dunque il seguente problema:
Progettare un programma a menù, con uso di funzioni, che offra le seguenti scelte: 1. Leggi due valori numerici; 2. Visualizza la somma; 3. Visualizza il prodotto; 4. Esci dal programma.
Esempio sulle funzioni in C++, Procedimento
Per realizzare questo semplice esercizio creiamo innanzitutto una funzione che crei un menù di scelta, la chiamo ad esempio menu_scelta.
Questo menù consentirà, di inserire gli elementi, fare la somma, il prodotto o di uscire dal programma.
Quindi realizziamo la funzione per l’inserimento insert() che restituirà il numero inserito.
Poi realizziamo le funzioni somma e prodotto che prenderanno come parametri due valori interi x e y e restituiranno rispettivamente il prodotto e la somma.
Quindi nel main in base alla scelta effettuata facciamo le operazioni.
Se si sceglie per prima l’opzione 2 o 3 avvisiamo l’utente che ancora deve inserire i dati.
Ecco dunque il listato completo dell’esempio sulle funzioni in C++:
#include <iostream>
using namespace std;
int somma(int x, int y); //prototipi di funzione
int prodotto(int x, int y); //prototipi di funzione
int insert(); //prototipi di funzione
int menu_scelta(void)
{
int selezione = 0;
do
{
cout<<endl<<"1 - Inserisci i numeri"<<endl;
cout<<"2 - Somma i numeri"<<endl;
cout<<"3 - Prodotto dei numeri"<<endl;
cout<<"4 - Esci"<<endl;
cout<<"Effettua una scelta:"<<endl;
cin>>selezione;
}
while (selezione<1 || selezione>4);
return selezione;
}
int main(void)
{
int scelta;
int a,b,s,p;
while((scelta=menu_scelta())!=4){
switch(scelta){
case 1:
a=insert();
b=insert();
break;
case 2:
if(!a || !b){
cout<<"Prima devi inserire i numeri!";
}
else {
s=somma(a,b);
cout<<"la somma e':"<<s<<endl;
}
break;
case 3:
if(!a || !b){
cout<<"Prima devi inserire i numeri!";
}
else {
p=prodotto(a,b);
cout<<"Il prodotto e':"<<p<<endl;
}
break;
case 4: break;
}
}
return 0;
}
int insert(){
int x;
cout<<"Inserisci un numero"<<endl;
cin>>x;
return x;
}
int somma(int x, int y) {
return x+y;
}
int prodotto(int x, int y) {
return x*y;
}
Si poteva anche richiedere, dopo il messaggio di avviso, l’inserimento dei due numeri in input. Come da esempio sotto:
if(!a || !b){
cout<<"Prima devi inserire i numeri!"<<endl;
a=insert();
b=insert();
}
else {
s=somma(a,b);
cout<<"la somma e':"<<s<<endl;
}
Chiaramente questa è solo una possibile soluzione al problema proposto, possono esserci tanti altri metodi risolutivi a questo esempio sulle funzioni in C++.