Algoritmi Politecnico di Milano C Primi programmi Politecnico di Milano
ESERCIZIO Dato un numero n stampare PRIMO se n è primo, NON PRIMO altrimenti
FORMALIZZAZIONE PROBLEMA Dato un numero n stampare PRIMO se n è primo, NON PRIMO altrimenti INPUT: numero OUTPUT: messaggio PRIMO o NON PRIMO DIALOGO 27 NON PRIMO
PROGETTARE Acquisisco numero Controllo se è primo If (è primo) printf(PRIMO); else printf(NON PRIMO);
PROGETTARE: controllo se è primo Penso a quello che conosco: un numero è primo se è divisibile solo per sé stesso e per 1 Divisibile: il resto della divisione intera è 0 In C la divisione intera si indica con / il resto con % Come farei a mano? Continuo a dividere il numero per tutti i numeri da 2 al numero – 1 Se il resto della divisione è SEMPRE 0 allora è primo Acquisisco il numero Controllo se è primo If (è primo) printf(PRIMO); else printf(NON PRIMO);
PROGETTARE: (è primo) Acquisisco numero Controllo se è primo If (è primo) printf(PRIMO); else printf(NON PRIMO); è primo è una condizione: deve tradursi nel valore di una variabile che lesecutore può controllare Uso un contatore che conta le volte che numero è divisibile: nVolteDivisibile = 0 è primo nVolteDivisibile > 0 non è primo
PROGETTARE: controllo se è primo Ci sarà un ciclo nel quale divido numero per un divisore, che la prima volta varrà 2 e poi Poi 3 poi 4 … : in ogni ciclo aumenterà di 1 Lobbiettivo del ciclo è contare quante volte il numero è divisibile quindi calcolare nVolteDivisibile Acquisisco il numero Controllo se è primo If (è primo) printf(PRIMO); else printf(NON PRIMO); Uso 3 variabili intere: numero, divisore, nVolteDivisibile
Stendere lalgoritmo #include main() { /* dichiarazioni */ int numero, divisore, nVolteDivisibile; /* Acquisisco Il numero */ scanf (%d, &numero); /* Controllo se è primo */ divisore = 2; nVolteDivisibile = 0; while (divisore < numero) { if (numero%divisore == 0) nVolteDivisibile = nVolteDivisibile + 1; divisore = divisore + 1; } if (nVolteDivisibile == 0) printf(PRIMO); else printf(NON PRIMO) }
Istruzioni eseguite numero divisore nVolteDivisibile ? ? ? scanf(%d, &numero) 7 ? ? divisore = 2; 7 2 ? nVolteDivisibile = 0; while (divisore < numero) if (numero%divisore == 0) divisore = divisore + 1; while (divisore < numero) if (numero%divisore == 0) divisore = divisore + 1; while (divisore < numero) if (numero%divisore == 0) divisore = divisore + 1; while (divisore < numero) if (numero%divisore == 0) divisore = divisore + 1; while (divisore < numero) if (numero%divisore == 0) divisore = divisore + 1; while (divisore < numero) if (nVolteDivisibile == 0) printf(PRIMO); Verificare
PROGETTARE: controllo se è primo Mi accorgo di fare troppi controlli inutili: posso pensare di diminuirne il numero fermandomi quando il Divisore = numero / 2 Posso diminuire il numero dei controlli anche fermandomi appena numero risulta divisibile: uso una variabile a 2 stati: isPrimo = 1 il numero è primo isPrimo = 0 il numero non è primo Acquisisco il numero Controllo se è primo If (è primo) printf(PRIMO); else printf(NON PRIMO);
Stendere lalgoritmo: seconda versione #include main() { /* dichiarazioni */ int numero, divisore, isPrimo; /* Acquisisco Il numero */ scanf (%d, &numero); /* Controllo se è primo */ divisore = 2; isPrimo= 1; while ((isPrimo == 1) && (divisore <= numero/2)) { if (numero%divisore == 0) isPrimo = 0; divisore = divisore + 1; } if (isPrimo == 1) printf(PRIMO); else printf(NON PRIMO) }
isStato = 1 While (condizione uscita) { If (evento) isStato = 0 Preparazione ciclo successivo } If (isStato == 1) …….. Pattern 4
contaEventi = 0 While (condizione uscita) { If (evento) contaEventi = contaEventi + 1 Preparazione ciclo successivo } If (contaEventi ………) …….. Pattern 5
ESERCIZIO 2.Modificare il programma precedente stampando le coordinate del punto di distanza massima 1.data una sequenza di n > 0 punti nel piano con n scelto dallutente, stampare la distanza massima dallorigine degli assi dei punti introdotti 3.Modificare il programma precedente stampando la distanza media
Formalizzazione problema INPUT: numero punti, sequenza coordinate x e y OUTPUT: distanza massima INPUT: numero punti, sequenza coordinate x e y OUTPUT: x i e y i coordinate punto distanza massima INPUT: numero punti, sequenza coordinate x e y OUTPUT: distanza media 1 2 3
PROGETTARE Acquisisco n (numero punti) Leggi punti e calcola distanza massima Stampa distanza massima
PROGETTARE: Leggi punti e calcola distanza massima Devo leggere n punti: pattern del ciclo a conteggio contenente la lettura della coordinata x e della coordinata y di un punto Calcola la distanza : dati x e y so calcolare la distanza dallorigine Distanza = sqrt (x*x + y*y) Mi devo ricordare: #include per usare sqrt( ) Acquisisco n (numero punti) Leggi punti e calcola distanza massima Stampa distanza massima
PROGETTARE: Leggi punti e calcola distanza massima Calcola la distanza MASSIMA: Mi ricordo che per trovare il massimo di una serie di numeri: 1.Usavo 2 variabili: distanza distanzaMax 2.Usavo un if posto nel ciclo: If (distanza > distanzaMax) distanzaMax = distanza 3.Inizializzavo distanzaMax Acquisisco n (numero punti) Leggi punti e calcola distanza massima Stampa distanza massima
#include main() { /* dichiarazioni */ int n, contatore; float distanza, distanzaMax, x, y; /* Acquisisco n */ scanf (%d, &n); /* leggi i punti e calcola la distanza massima */ contatore = 0; distanzaMax = 0; while (contatore < n) { scanf(%f, &x); scanf( %f, &y); distanza = sqrt (x*x + y*y); if (distanza > distanzaMax) distanzaMax = distanza; contatore = contatore + 1; } /* stampa distanza massima */ printf(%f, distanzaMax); } Stendere lalgoritmo Pattern del ciclo a conteggio matematica massimo
Formalizzazione problema INPUT: numero punti, sequenza coordinate x e y OUTPUT: distanza massima INPUT: numero punti, sequenza coordinate x e y OUTPUT: x i e y i coordinate punto distanza massima INPUT: numero punti, sequenza coordinate x e y OUTPUT: distanza media 1 2 3
PROGETTARE Acquisisco n (numero punti) Leggi punti e calcola distanza massima Stampa le coordinate del punto di distanza massima
PROGETTARE Acquisisco n (numero punti) Leggi punti e calcola distanza massima Stampa le coordinate del punto di distanza massima Parto da fondo: dal risultato che devo ottenere: Le coordinate del punto di distanza massima: Se alla fine le devo stampare allora prima le devo salvare Quando devo salvare le coordinate del punto di distanza massima? Provo a risolvere il problema a mano: Le salvo quando salvo la nuova distanza massima
#include main() { /* dichiarazioni */ int n, contatore; float distanza, distanzaMax, x, y, xMax, yMax; /* Acquisisco n */ scanf (%d, &n); /* leggi i punti e calcola la distanza massima */ contatore = 0; distanzaMax = 0; while (contatore < n) { scanf(%f, &x); scanf( %f, &y); distanza = sqrt (x*x + y*y); if (distanza > distanzaMax) { distanzaMax = distanza; xMax = x; yMax = y; } contatore = contatore + 1; } /* stampa distanza massima */ printf(punto di distanza massima x = %f y = %f,xMax, yMax); } Stendere lalgoritmo Modifica codice aggiungendo il salvataggio delle coordinate del punto di distanza massima Aggiungo dichiarazione due variabili per salvare le coordinate del punto di distanza massima Stampa coordinate punto di distanza massima
Formalizzazione problema INPUT: numero punti, sequenza coordinate x e y OUTPUT: distanza massima INPUT: numero punti, sequenza coordinate x e y OUTPUT: x i e y i coordinate punto distanza massima INPUT: numero punti, sequenza coordinate x e y OUTPUT: distanza media 1 2 3
PROGETTARE Acquisisco n (numero punti) Leggi punti e calcola distanza media Stampa la distanza media
PROGETTARE Acquisisco n (numero punti) Leggi punti e calcola distanza media Stampa la distanza media Cosa conosco del problema? La media = Σ distanza i / n Quindi devo calcolare la somma delle distanze e stamperò: media = sommaDistanze / n
PROGETTARE Acquisisco n (numero punti) Leggi punti e calcola la somma delle distanze Stampa la distanza media Per calcolare la somma: 1.Uso una variabile somma 2.Nel ciclo incremento somma della distanza appena calcolata somma = somma + distanza 1.inizializzo somma a 0 La variabile somma si chiama ACCUMULATORE
#include main() { /* dichiarazioni */ int n, contatore; float distanza, somma,; /* Acquisisco n */ scanf (%d, &n); /* leggi i punti e calcola la somma delle distanze*/ contatore = 0; somma = 0; while (contatore < n) { scanf(%f, &x); scanf( %f, &y); distanza = sqrt (x*x + y*y); somma = somma + distanza; contatore = contatore + 1; } /* stampa media*/ printf(la distanza media è %f,somma / n); } Stendere lalgoritmo Dichiaro somma Inizializzo somma Modifica codice con incremento somma
esercizio data una sequenza di n punti nel piano che termina con linserimento delle coordinate dellorigine stampare la distanza minima dallorigine degli assi dei punti introdotti E se il problema fosse? Per esercizio fare la formalizzazione del problema e la progettazione
Formalizzazione problema INPUT: sequenza di punti che termina con 0 0 OUTPUT: distanza minima 1
PROGETTARE Acquisisco le coordinate dei punti e calcolo la distanza minima Stampa la distanza minima
PROGETTARE: Acquisisco le coordinate dei punti e calcolo la distanza minima Acquisisco le coordinate dei punti e calcolo la distanza minima Stampa la distanza minima Uso il pattern della sequenza di valori che finisce con 0 Leggi il primo valore Inizializza While (il valore non è lultimo) { Esegui loperazione Leggi il prossimo valore }
PROGETTARE: esegui loperazione Uso il pattern della sequenza di valori che finisce con 0 Leggi il primo valore Inizializza While (il valore non è lultimo) { Esegui loperazione Leggi il prossimo valore } Loperazione da eseguire assomiglia a quella del calcolo del massimo quindi: 1.Uso due variabili distanza e distanza minima 2.Calcolo la distanza 3.La confronto con distanza minima e sostituisco se è più piccola
Date le informazioni mese e anno visualizzare il numero di giorni del mese ESERCIZIO 30 giorni ha novembre con april giugno e settembre di 28 ce nè uno tutti gli altri ne hanno 31 Un anno è bisestile se lanno è divisibile per 4 e non per 100 o è divisibile per 400
PROGETTARE Acquisisco mese e anno Calcolo il numero di giorni del mese Stampo i giorni
PROGETTARE: Calcolo il numero di giorni del mese Acquisisco mese e anno Calcolo il numero di giorni del mese Stampo i giorni Conosco che lesecutore macchina C, se a e b sono interi: a / b quoziente della divisione intera a % b resto della divisione intera Es: 13 / 3 = 4 13 % 3 = 1 Mi concentro sulle operazioni in alternativa: If (mesi con 30 giorni) giorni = 30 else if (febbraio) gestisco febbraio else giorni = 31
PROGETTARE: febbraio gestisco è bisestile: se lanno è divisibile per 4 e non per 100 o è divisibile per 400 If (è bisestile) giorni = 29 else giorni = 28 If ( ((anno % 4 == 0) && (anno % 100 != 0) ) || (anno % 400 == 0))
#include main() { /* dichiarazioni */ int mese, anno, giorni; /* Acquisisco mese e anno */ printf(inserisci mese e anno\n ); scanf (%d%d, &mese, &anno); /* Calcolo il numero di giorni del mese */ If ((mese == 4) || (mese == 11) || (mese == 6) || (mese == 9)) giorno = 30; else if (mese == 2) if (((anno % 4 == 0) && (anno % 100 != 0)) || (anno % 400 == 0)) giorno = 29; else giorno = 28; else giorno = 31; /* stampo giorno */ printf(i giorni del mese %d sono %d, mese, giorno); } Stendere lalgoritmo
ESERCIZIO Scrivere un programma che data una frase contenente parole in caratteri minuscoli separate da SPAZI che termini con UN A CAPO, stampi per ogni vocale il numero delle volte che è presente nella frase. Se vengono introdotti caratteri diversi da una lettera minuscola o un blank o un a capo il programma li ignora
PROGETTARE Acquisisco la frase e conto le vocali Stampo il numero delle occorrenze di ogni vocale
PROGETTARE:stampo il numero di occorrenze di ogni vocale La parte PRECEDENTE del codice ha come obbiettivo la valorizzazione di questi contatori Parto dal basso: 1.Per ogni vocale devo avere un contatore che vale il numero di volte che lho trovata nella frase 2.nA nE nI nU nO sono i contatori 3.Allinizio del programma inizializzo i contatori a 0 Acquisisco la frase e conto le vocali Stampo il numero delle occorrenze di ogni vocale
PROGETTARE: Acquisisco la frase e conto le vocali Allinterno del ciclo controllo il carattere se è una vocale incremento il contatore corrispondente So leggere un carattere alla volta quindi per leggerli tutti ci vuole un ciclo Acquisisco la frase e conto le vocali Stampo il numero delle occorrenze di ogni vocale Una frase è una sequenza di caratteri che finisce con a capo = \n quindi USO il pattern sequenza di interi che finisce con 0
#include main() { /* dichiarazioni */ char c; int nA, nE, nI, nU, nO; /* Acquisisco la frase e conto le vocali */ nA = 0; nE = 0; nI = 0; nU = 0; nO = 0; scanf(%c, &c); Stendere lalgoritmo: prima parte Inizializzo i contatori Leggo il primo carattere
while (c != \n) { if (c == a) nA++; else if (c == e) nE++; else if (c == i) nI++; else if (c == u) nU++; else if (c == o) nO++; scanf(%c, &c); } /* Stampo il numero delle occorrenze di ogni vocale */ printf(a = %d e = %d i = %d u = %d o = %d, nA, nE, nI, nU, nO); } Stendere lalgoritmo: continua Eseguo lazione: controllo il carattere appena letto Non è il carattere di A CAPO Leggo il prossimo carattere Sinonimo di nU = nU + 1
Istruzioni eseguitecnAnEnInUnO ???????????? nA = 0;?0???? nE = 0;?00??? nI = 0;?000?? nU = 0;?0000? nO = 0;?00000 scanf(%c, &c);f00000 while (c != \n)f00000 if (c == a)f00000 else if (c == e)f00000 else if (c == i) f00000 else if (c == u)f00000 else if (c == o)f00000 scanf(%c, &c);i00000 while (c != \n)i00000 if (c == a)i00000 else if (c == e)i00000 else if (c == i) i00000 nI++;i00100 Verificare
Istruzioni eseguitecnAnEnInUnO scanf(%c, &c);n00100 while (c != \n)n00100 if (c == a)n00100 else if (c == e)n00100 else if (c == i) n00100 else if (c == u)n00100 else if (c == o)n00100 scanf(%c, &c);e00100 while (c != \n)e00100 if (c == a)e00100 else if (c == e)e00100 nE++;e01100 scanf(%c, &c);\n01100 while (c != \n)\n01100 printf(a = %d e … Verificare