Algoritmi Algoritmi Politecnico di Milano Politecnico di Milano Progettare Fasi per progettare un algoritmo • Formalizzare il problema • Progettare • Stendere l’algoritmo • Verificare problema • Problema: Un comune decide di mettere una tassa sul passo carrabile di 9.8 euro al metro quadro. Ogni passo carrabile è stato denunciato definendone le dimensioni in altezza e larghezza. Calcolare la tassa che si deve pagare per ogni passo carrabile Formalizzazione problema • Problema: Un comune decide di mettere una tassa sul passo carrabile di 9.8 euro al metro quadro. Ogni passo carrabile è stato denunciato definendone le dimensioni in altezza e larghezza. Calcolare la tassa che si deve pagare per ogni passo carrabile INPUT: altezza e larghezza passo carrabile OUTPUT: tassa Raffinamento formalizzazione Definizione: INPUT: altezza e larghezza passo carrabile OUTPUT: tassa Raffinamento: Il Dialogo Uomo – Computer Inserisci la lunghezza del passo carrabile: 4 Inserisci la larghezza del passo carrabile: 5 tassa da pagare 196 Progettare Comincio a definire I passi fondamentali che deve fare l’algoritmo: 1. Acquisire I valori in input 2. Calcolare la tassa 3. Visualizzare la tassa Progettare: 1 acquisire I valori in input • Ogni valore digitato dall’utente (es. 4 e 5) deve essere memorizzato per poter essere utilizzato nel calcolo dell’area – Decido di utilizzare due celle di memoria: lunghezza larghezza – Conosco che l’operazione che prende I dati da tastiera e li deposita in memoria è per la macchina C la scanf scanf(lunghezza) scanf(larghezza) Progettare: 2 Calcolare la tassa • So calcolare la tassa “a mano” tassa = lunghezza * larghezza * 9.8 • Dalla formula deduco che mi serve utilizzare un’altra cella di memoria per memorizzare il valore della tassa tassa • Conosco l’istruzione di assegnamento della macchina C che ha lo stesso aspetto della formula matematica Progettare:3 Visualizzare la tassa 198 tassa • Conosco l’istruzione di printf che mi permette di visualizzare una cella di memoria Stendere l’algoritmo main() { /* Acquisire I valori in input */ printf("Inserisci la lunghezza del passo carrabile:" ); scanf (lunghezza); printf("Inserisci la larghezza del passo carrabile:" ); scanf(larghezza); /* Calcolare la tassa */ tassa = lunghezza * larghezza * 9.8; /* Visualizzare la tassa */ printf(“tassa da pagare “); printf(tassa); } Verificare: simuliamo l’esecuzione ? ? main() tassa lunghezza { /* Acquisire I valori in input */ printf("Inserisci la lunghezza del passo carrabile:" ); scanf (lunghezza); printf("Inserisci la larghezza del passo carrabile:" ); scanf(larghezza); ? 4 /* Calcolare la tassa */ tassa lunghezza tassa = lunghezza * larghezza * 9.8; /* Visualizzare la tassa */ 198 4 printf(“tassa da pagare “); tassa lunghezza printf(tassa); } ? larghezza 5 larghezza 5 larghezza Pattern 1 Acquisisci i dati di ingresso Calcola i risultati Visualizza i risultati Esercizi simili • Calcolare il volume di un cilindro conoscendo raggio e altezza • Vengono forniti da tastiera i risultati di un referendum: – Numero iscritti a votare – Numero votanti – Numero si – Numero no Calcolare la percentuale di votanti sul totale degli iscritti, le percentuali dei si e dei no rispetto al numero dei votanti Problema • Scrivere un programma che legge in ingresso un carattere e stampa se corrisponde a una cifra o a una lettera alfabetica o a un altro carattere, nel caso sia una lettera segnalare il caso particolare che sia una vocale o una consonante e il caso particolare che sia minuscola. Es: • 3 cifra • D lettera consonante • e lettera vocale minuscola • d lettera consonante minuscola • E lettera vocale • < altro carattere Formalizzazione problema • INPUT: carattere della tastiera • OUTPUT:messaggi in alternativa – cifra – carattere » EVENTUALMENTE » EVENTUALMENTE – Altro vocale o consonante minuscola Progettare Acquisisco il carattere Emetto i messaggi in alternativa /* acquisisco il carattere /* scanf(c); /* Emetto i messaggi in alternativa */ If (c è una cifra) Le azioni printf sono in alternativa uso if I casi sono mutuamente esclusivi printf(“cifra”); else if (c è una lettera) analizzo la lettera else printf(“altro carattere”); L’azione viene eseguita dalla macchina C solo nel caso c sia una lettera Progettare /* analizzo la lettera */ If (c è una vocale) printf(“vocale”); else printf(“consonante”); If (c è minuscola) printf(“minuscola”); I casi non sono mutuamente esclusivi: c può essere una vocale ed essere minuscola Progettare c è una cifra (c >= ‘0’) && (c<= ‘9’) c è una lettera (c >= ‘a’) && (c <= ‘z’) || (c >= ‘A’) && (c <= ‘Z’) So che nella tabella ascii le lettere sono codificate sequenzialmente seguendo l’ordine c è una vocale (c == ‘a’) || (c == ‘e’) || (c== ‘i’) || (c == ‘o’) || (c == ‘u’) c è minuscola (c >= ‘a’) && (c <= ‘z’) Stendere l’algoritmo /* acquisisco il carattere /* scanf(c); /* Emetto i messaggi in alternativa */ If ((c >= ‘0’) && (c<= ‘9’)) printf(“cifra”); else if ((c >= ‘a’) && (c <= ‘z’) || (c >= ‘A’) && (c <= ‘Z’) ) /* analizzo la lettera */ If ((c == ‘a’) || (c == ‘e’) || (c== ‘i’) || (c == ‘o’) || (c == ‘u’)) printf(“vocale”); else printf(“consonante”); If ((c >= ‘a’) && (c <= ‘z’)) printf(“minuscola”); else printf(“altro carattere”); Verificare Istruzioni eseguite c video ? scanf(c) 4 4 If ((c >= ‘0’) && (c<= ‘9’)) 4 4 printf(“cifra”); 4 4 cifra Verificare Istruzioni eseguite c video ? scanf(c) d d If ((c >= ‘0’) && (c<= ‘9’)) d d else if ((c >= ‘a’) && (c <= ‘z’) || (c >= ‘A’) && (c <= ‘Z’) ) d d If ((c == ‘a’) || (c == ‘e’) || (c== ‘i’) || (c == ‘o’) || (c == ‘u’)) d d printf(“consonante”); d d consonante If ((c >= ‘a’) && (c <= ‘z’)) d d consonante printf(“minuscola”); d d consonante minuscola Esercizi simili • Date le misure a e b di un rettangolo potenziale (a e b possono essere nulle o negative) si vuole sapere si tratta di un quadrato, di un rettangolo, di un segmento, di un punto o di un caso impossibile • Dati tre numeri interi calcolare il massimo e stamparlo Problema • Data una sequenza di numeri naturali che finisce con 0 trovare il massimo dei numeri inseriti Formalizzazione problema • Problema: Data una sequenza di numeri naturali che finisce con 0 trovare il massimo dei numeri inseriti INPUT: sequenza di naturali che finisce con 0 OUTPUT: numero massimo Raffinamento formalizzazione Definizione: INPUT: sequenza di naturali che finisce con 0 OUTPUT:numero massimo Raffinamento: Il Dialogo Uomo – Computer 34 61 9 0 massimo 61 Progettare Comincio a definire I passi fondamentali che deve fare l’algoritmo: 1. Acquisire I valori in input 2. Visualizzare il massimo Progettare Acquisire I valori in input • Provo a risolvere io il problema e osservo le operazioni che compio • • Noto che pur non memorizzando tutti I numeri riesco a trovare il massimo Noto che in ogni momento memorizzo il numero appena inserito dall’utente e il massimo dei numeri precedentemente inseriti • In memoria definisco le variabili: 8 numero 56 massimo Progettare Acquisire I valori in input • Provo a risolvere io il problema e osservo le operazioni che compio • Noto che continuo a ripetere il confronto fra il numero inserito e il massimo dei precedenti Noto che se il numero inserito è più grande diventa il massimo che memorizzo • Stendere l’algoritmo main() { Il massimo è /* Acquisire I valori in inputil*/primo scanf(numero); numero Non è l’ultimo numero massimo = numero; while (numero != 0) { if (numero >massimo) massimo = numero; Noto che continuo a ripetere il confronto fra il numero inserito e il massimo dei precedenti scanf(numero); } /* Visualizzare il massimo */ printf(massimo); } Noto che se il numero inserito è più grande diventa il massimo che memorizzo Verificare Istruzioni eseguite c massimo video ? ? scanf(numero) 34 ? 34 massimo = numero; while (numero != 0) if (numero >massimo) 34 34 34 34 34 34 34 34 34 scanf(numero); 61 34 34 61 While (numero != 0) 61 34 34 61 if (numero >massimo) 61 34 34 61 massimo = numero; 61 61 34 61 scanf(numero); 9 61 34 61 9 While (numero != 0) 9 61 34 61 9 if (numero >massimo) 9 61 34 61 9 scanf(numero); 0 61 34 61 9 While (numero != 0) 0 61 34 61 9 0 printf(massimo) 0 61 61 Pattern 2 Leggi il primo valore Inizializza While (il valore non è l’ultimo) { Esegui l’operazione Leggi il prossimo valore } Problema • Visualizzare n naturali della tabellina del 2 con n scelto dall’utente Formalizzazione problema • Problema: Visualizzare n naturali della tabellina del 2 con n scelto dall’utente INPUT: n, quantità numeri da stampare OUTPUT: sequenza di n numeri multipli di 2 Raffinamento formalizzazione Definizione: INPUT: n, quantità numeri da stampare OUTPUT: sequenza di n numeri multipli di 2 Raffinamento: Il Dialogo Uomo – Computer 3 246 Progettare Comincio a definire I passi fondamentali che deve fare l’algoritmo: 1. Acquisire il valore n 2. Visualizzo i primi n multipli di 2 Progettare Visualizzo i primi n multipli di 2 • Parto dal risultato: • Devo visulizzare n numeri ciclo che si ripete n volte e che contiene una printf del numero da visualizzare • Uso il pattern del ciclo a conteggio Progettare Pattern ciclo a conteggio contatore = 0 while (contatore < numero volte da ripetere) { azione da ripetere contatore = contatore + 1; } Stendere l’algoritmo main() { /* acquisisco quantità n */ scanf(n); /* visualizzo i primi n multipli di n */ Contatore = 0; While (contatore < n) { printf (multiplo2); contatore = contatore + 1; } Mi accorgo che qualcosa non funziona, la variabile multiplo2 è solo visualizzata e mai valorizzata: Provo a fare il trace Verificare Istruzioni eseguite n contatore multiplo2 video ? ? ? scanf(n) 3 ? ? 3 contatore = 0 3 0 ? 3 while (contatore < n) printf(multiplo2) 3 3 0 0 ? ? 3 ? Mi fermo qui: sul video appare un numero qualsiasi mentre dovrebbe essere 2 e poi 4 e poi 6 …questi sono i valori che dovrebbe assumere multiplo2 … Stendere l’algoritmo main() { /* acquisisco quantità n */ scanf(n); /*visualizzo i primi n multipli di n */ multiplo2 = 2; contatore = 0; while (contatore < n) { printf (multiplo2); multiplo2 = multiplo2 + 2; contatore = contatore + 1; } main() { /* acquisisco quantità n */ scanf(n); /*visualizzo i primi n multipli di n */ multiplo2 = 0; contatore = 0; while (contatore < n) { multiplo2 = multiplo2 + 2; printf (multiplo2); contatore = contatore + 1; } Stendere l’algoritmo main() { /* acquisisco quantità n */ scanf(n); /* visualizzo i primi n multipli di n */ contatore = 1; While (contatore <= n) { printf (contatore*2); contatore = contatore + 1; } Noto che il numero da stampare è sempre il doppio di contatore: aggiusto l’algoritmo di conseguenza Problemi simili • Visualizzare a video la parola ciao un numero di volte scelto dall’utente • Calcolare il prodotto di una sequenza di numeri che termina con 0 • Stampare il valore della potenza di base m ed esponente n > 0 • data una sequenza di n punti nel piano con n scelto dall’utente, stampare la distanza massima dall’origine degli assi dei punti introdotti • Modificare il programma precedente stampando le coordinate del punto di distanza massima • Modificare il programma precedente stampando la distanza media suggerimenti • Scompongo la soluzione in un piccolo numero di “big step” • Comicio a riempire l’algoritmo con printf e scanf facendomi guidare dal dialogo uomo computer • Parto dal risultato da ottenere e torno indietro • Uso l’analogia: come potrei farlo io a mano? • Uso pattern conosciuti • Verifico, verifico, verifico …