Algoritmi 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 Acquisire I valori in input Calcolare la tassa Comincio a definire I passi fondamentali che deve fare l’algoritmo: Acquisire I valori in input Calcolare la tassa 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: 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) lunghezza 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 Conosco l’istruzione di assegnamento della macchina C che ha lo stesso aspetto della formula matematica tassa
Progettare:3 Visualizzare la tassa Conosco l’istruzione di printf che mi permette di visualizzare una cella di memoria tassa 198
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() { /* 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); } tassa ? lunghezza larghezza tassa ? lunghezza 4 larghezza 5 tassa 198 lunghezza 4 larghezza 5
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 vocale o consonante EVENTUALMENTE minuscola Altro
Progettare Acquisisco il carattere Emetto i messaggi in alternativa scanf(c); /* Emetto i messaggi in alternativa */ If (c è una cifra) printf(“cifra”); else if (c è una lettera) analizzo la lettera else printf(“altro carattere”); Le azioni printf sono in alternativa uso if I casi sono mutuamente esclusivi 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’) c è una vocale (c == ‘a’) || (c == ‘e’) || (c== ‘i’) || (c == ‘o’) || (c == ‘u’) c è minuscola (c >= ‘a’) && (c <= ‘z’) So che nella tabella ascii le lettere sono codificate sequenzialmente seguendo l’ordine
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”); 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’) || d d (c >= ‘A’) && (c <= ‘Z’) ) If ((c == ‘a’) || (c == ‘e’) || (c== ‘i’) d d || (c == ‘o’) || (c == ‘u’)) 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 Acquisire I valori in input Visualizzare il massimo Comincio a definire I passi fondamentali che deve fare l’algoritmo: Acquisire I valori in input Visualizzare il massimo
Acquisire I valori in input 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: massimo 56 numero 8
Acquisire I valori in input 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
Il massimo è il primo numero Stendere l’algoritmo main() { /* Acquisire I valori in input */ scanf(numero); massimo = numero; while (numero != 0) { if (numero >massimo) } /* Visualizzare il massimo */ printf(massimo); Il massimo è il primo numero Non è l’ultimo numero 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
Verificare Istruzioni eseguite c massimo video ? ? ? ? scanf(numero) 34 ? 34 massimo = numero; 34 34 34 while (numero != 0) 34 34 34 if (numero >massimo) 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 2 4 6
Progettare Acquisire il valore n Visualizzo i primi n multipli di 2 Comincio a definire I passi fondamentali che deve fare l’algoritmo: Acquisire il valore n Visualizzo i primi n multipli di 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
Pattern 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) 3 0 ? 3 printf(multiplo2) 3 0 ? ? 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 …