EuraStudy
Appunti/Informatica/Algoritmi, problem solving e pseudocodifica
Appunti · InformaticaIT · Maturità

Algoritmi, problem solving e pseudocodifica

Un algoritmo è una sequenza finita e non ambigua di passi che, a partire da dati di ingresso, produce in un numero finito di operazioni la soluzione di un problema. Questo appunto guida dall'analisi del problema alla sua formalizzazione, presentando le proprietà fondamentali degli algoritmi, le strategie di problem solving (analisi, scomposizione top-down, raffinamenti successivi), le tre strutture di controllo della programmazione strutturata (sequenza, selezione, iterazione) garantite dal teorema di Böhm-Jacopini, e i due linguaggi di descrizione — pseudocodice e diagrammi di flusso. Si chiude con i primi cenni a correttezza ed efficienza, valutata contando le operazioni eseguite.

5 sezioni·~24 min di lettura·3 competenze·Livello Base 1 · Standard 3 · Approfondimento 1·Verificato · 07/2026

T·0111 / 14
Profilo d’esame
Affrontare e risolvere problemi elaborando opportune strategie algoritmiche e formalizzandole con pseudocodice e diagrammi di flussoComprendere il ruolo dell'informatica come strumento di modellizzazione e risoluzione di problemiCogliere il rapporto tra il problema, il modello individuato e la sua soluzione algoritmica, valutandone correttezza ed efficienza
Operatori:analizzaspiegadescrivideterminaclassificaconfrontaillustragiustificainterpretatraduci

livello base

È richiesto saper analizzare un problema, scomporlo e descriverne la soluzione con le tre strutture di controllo, in pseudocodice o con un diagramma di flusso corretto.

livello avanzato

Nell'opzione Scienze Applicate si aggiungono la dimostrazione informale di correttezza (invarianti, casi limite) e la valutazione dell'efficienza tramite il conteggio delle operazioni e il confronto fra algoritmi alternativi.

Profondità

Profondità di lettura: Approfondimento

Testo

Dimensione del testo: Standard

Contenuti · 5 sezioni▾
  1. Algoritmi, problem solving e pseudocodifica
    • 01Dal problema all'algoritmo: analisi e modellizzazione○
    • 02Proprietà degli algoritmi e formalismi di rappresentazione◐
    • 03Le strutture di controllo: sequenza, selezione, iterazione◐
    • 04Pseudocodice e diagrammi di flusso◐
    • 05Cenni a correttezza ed efficienza●
§ 01

Dal problema all'algoritmo: analisi e modellizzazione#

●○○BaseLPOSA-informatica-fondamenti-algoritmi — strategie di problem solving: analisi del problema, dati di ingresso/uscita, scomposizione (top-down) e raffinamenti successivi

Il processo di problem solving: dal problema all'algoritmo

Dal problema all’algoritmoGrafo, Problema → Analisi · input/output, Analisi · input/output → Scomposizione top-down, Scomposizione top-down → sottoproblema 1, Scomposizione top-down → sottoproblema 2, Scomposizione top-down → sottoproblema 3, sottoproblema 1 → Algoritmo, sottoproblema 2 → Algoritmo, sottoproblema 3 → Algoritmo, Algoritmo → Pseudocodice / codificaProblemaAnalisi · input/outputScomposizionetop-downsottoproblema 1sottoproblema 2sottoproblema 3AlgoritmoPseudocodice /codifica
Fig. 1Il problem solving: si analizza il problema (input/output), lo si scompone top-down in sottoproblemi, si progetta l’algoritmo e infine lo si traduce in pseudocodice/codice.

Punti chiave

Risolvere un problema con il calcolatore significa, prima ancora di scrivere una sola istruzione, comprenderlo a fondo e descriverne la soluzione come procedimento meccanizzabile: questa è l'attività di problem solving, di cui l'algoritmo è il prodotto finale. Il punto di partenza non è il codice, ma l'analisi del problema, cioè la chiara distinzione fra ciò che si conosce e ciò che si vuole ottenere.
L'analisi individua anzitutto i dati di ingresso (input) — le informazioni note o fornite — e i dati di uscita (output) — i risultati attesi — collegandoli attraverso le relazioni che governano il problema. Definire con precisione input e output significa già delimitare il problema: una specifica ambigua porta inevitabilmente a un algoritmo sbagliato, perché la macchina esegue alla lettera ciò che le si dice, non ciò che si intendeva dire.
I problemi complessi si affrontano con la strategia top-down: si parte dal problema nel suo insieme e lo si scompone in sottoproblemi più semplici, ciascuno dei quali può essere affrontato e risolto separatamente. Questo procedimento di raffinamenti successivi (stepwise refinement) prosegue finché ogni sottoproblema è così elementare da tradursi direttamente in poche istruzioni; la composizione delle soluzioni parziali ricostruisce la soluzione complessiva.
Il prodotto dell'analisi è il modello del problema: una rappresentazione astratta che trascura i dettagli irrilevanti e conserva solo ciò che serve a calcolare la soluzione. Solo dopo aver costruito il modello e progettato l'algoritmo ha senso passare alla pseudocodifica e, infine, alla codifica in un linguaggio di programmazione. Saltare l'analisi per scrivere subito codice è l'errore più frequente e più costoso.
Esempio svolto

Analisi e scomposizione di un problema

Analizza il problema «calcolare la media aritmetica dei voti di uno studente»: individua i dati di ingresso e di uscita, esprimi la relazione che li lega e scomponi il problema in sottoproblemi elementari.

  1. 01Individuazione dell'output

    Il risultato richiesto è un solo valore: la media aritmetica dei voti, un numero reale.

  2. 02Individuazione dell'input

    Servono i voti dello studente, cioè una sequenza di n valori numerici, e implicitamente la loro quantità n.

  3. 03Relazione tra input e output

    La media è la somma dei voti divisa per il loro numero.

  4. 04Scomposizione top-down

    Sottoproblema 1: leggere i voti e contarli (determinare n). Sottoproblema 2: calcolare la somma S dei voti. Sottoproblema 3: dividere S per n e restituire il risultato (con la condizione n > 0 per evitare la divisione per zero).

Risultato: Output: media M; input: i voli v_1, ..., v_n e il loro numero n; relazione M = S/n; il problema si scompone in «leggi e conta», «somma», «dividi e restituisci».

Obiettivo Maturità

  • Saper distinguere con precisione, dato un testo, i dati di ingresso dai dati di uscita e formulare la specifica del problema: è il primo passo valutato in qualunque esercizio di progettazione di algoritmi.
  • Saper applicare la scomposizione top-down spiegando come un problema viene suddiviso in sottoproblemi e perché la strategia di raffinamenti successivi rende gestibile la complessità.

Errori frequenti

  • Iniziare a scrivere l'algoritmo senza aver prima identificato input e output: si finisce per «inseguire» il problema invece di risolverlo, producendo soluzioni incomplete o incoerenti.
  • Confondere il problema (la specifica «che cosa») con l'algoritmo (la procedura «come»): possono esistere molti algoritmi diversi per lo stesso problema, e descriverne uno non equivale a definire il problema.

Approfondimento

Sul piano teorico un problema si formalizza come una funzione (o relazione) che a ogni istanza dei dati di ingresso associa i dati di uscita ammissibili: il dominio è l'insieme degli input validi, il codominio l'insieme delle possibili risposte, e risolvere il problema significa realizzare quella funzione con un procedimento effettivo. Questa lettura permette di distinguere tre grandi famiglie che ricorrono in tutto il programma: i problemi di decisione, la cui uscita è un semplice «sì/no» (un numero è primo?); i problemi di ricerca, che chiedono di esibire un oggetto con una data proprietà (trovare la posizione di un valore in un elenco); i problemi di ottimizzazione, che fra tutte le soluzioni ammissibili cercano la migliore secondo un criterio (il cammino più breve, la spesa minima). Un problema è ben posto quando la specifica è completa e non contraddittoria, cioè per ogni input ammissibile l'output atteso esiste ed è univocamente determinato. La fase di analisi è l'esercizio concreto del pensiero computazionale (computational thinking, J. Wing), che si articola in quattro operazioni intrecciate: la decomposizione (spezzare il problema in parti), il riconoscimento di schemi ricorrenti (pattern), l'astrazione (costruire il modello trascurando i dettagli irrilevanti) e la progettazione dell'algoritmo. È bene sapere fin d'ora che non tutti i problemi ben posti ammettono un algoritmo risolutivo: esistono problemi indecidibili, di cui la teoria della computabilità dimostra l'insolubilità meccanica.

Ripasso attivo

Dato il problema «calcolare la media aritmetica dei voti di uno studente», svolgi l'analisi: indica i dati di ingresso e di uscita, scrivi la relazione che li lega e scomponi il problema top-down in almeno tre sottoproblemi elementari.

Richiamo attivo

Ricorda i punti chiave — poi rivela.

Fonti: Indicazioni Nazionali per i Licei (DPR 89/2010, DM 211/2010) — Obiettivi Specifici di Apprendimento (Ministero dell'Istruzione e del Merito (MIM))

§ 02

Proprietà degli algoritmi e formalismi di rappresentazione#

●●○StandardLPOSA-informatica-fondamenti-algoritmi — concetto di algoritmo: proprietà (finitezza, determinismo, generalità, eseguibilità) e formalismi di rappresentazione

Le quattro proprietà fondamentali di un algoritmo

Le quattro proprietà di un algoritmoGrafo, Algoritmo → Finitezza, Algoritmo → Determinismo, Algoritmo → Generalità, Algoritmo → EseguibilitàAlgoritmoFinitezzaDeterminismoGeneralitàEseguibilità
Fig. 2Finitezza: termina in un numero finito di passi. Determinismo: ogni passo è univoco, non ambiguo. Generalità: risolve una classe di problemi. Eseguibilità: ogni passo è realizzabile.

Punti chiave

Non ogni elenco di istruzioni è un algoritmo: perché lo sia, deve soddisfare alcune proprietà fondamentali. La finitezza richiede che l'algoritmo termini dopo un numero finito di passi; il determinismo (o non ambiguità) impone che ogni passo sia definito in modo univoco, così che la stessa sequenza di passi a partire dagli stessi dati produca sempre lo stesso risultato.
La generalità richiede che l'algoritmo risolva non un singolo caso, ma un'intera classe di problemi dello stesso tipo: l'algoritmo della media deve funzionare per qualunque insieme di voti, non solo per uno specifico. L'eseguibilità (o realizzabilità) impone infine che ogni passo sia un'operazione effettivamente compibile dall'esecutore, con le risorse a sua disposizione.
A queste si affianca la richiesta che i dati di ingresso e di uscita siano ben definiti: un algoritmo riceve zero o più input e produce almeno un output. Un procedimento che non termina (un ciclo infinito), che contiene un passo ambiguo, o che richiede un'operazione impossibile, non è un algoritmo corretto, anche se a prima vista «sembra» risolvere il problema.
Lo stesso algoritmo può essere descritto con formalismi diversi: il linguaggio naturale (chiaro ma ambiguo), il diagramma di flusso (rappresentazione grafica), lo pseudocodice (a metà fra linguaggio naturale e linguaggio di programmazione) e infine un linguaggio di programmazione (eseguibile dalla macchina). I formalismi intermedi — pseudocodice e diagrammi di flusso — servono a progettare e comunicare l'algoritmo senza vincolarsi alla sintassi di uno specifico linguaggio.
Esempio svolto

Verifica delle proprietà su un procedimento dato

È dato il seguente procedimento: «parti da x = 1; finché x è diverso da 0, aumenta x di 1; quando x = 0 stampa x». Stabilisci se è un algoritmo, verificando le quattro proprietà fondamentali.

  1. 01Eseguibilità

    Ogni passo (assegnazione, confronto, incremento, stampa) è un'operazione elementare effettivamente compibile: la proprietà è soddisfatta.

  2. 02Determinismo

    Ogni passo è definito in modo univoco, senza ambiguità: la proprietà è soddisfatta.

  3. 03Finitezza

    Partendo da x = 1 e incrementando, x assume i valori 2, 3, 4, ... e non vale mai 0: la condizione di uscita non si verifica mai e il ciclo non termina.

  4. 04Conclusione

    Poiché la finitezza è violata (ciclo infinito), il procedimento NON è un algoritmo, pur sembrando ben definito.

Risultato: Non è un algoritmo: viola la proprietà di finitezza perché la condizione di terminazione non è mai raggiunta.

Obiettivo Maturità

  • Conoscere ed enunciare con precisione le quattro proprietà fondamentali (finitezza, determinismo, generalità, eseguibilità) e saperle riconoscere o negare in un procedimento dato.
  • Saper classificare i formalismi di rappresentazione (linguaggio naturale, diagramma di flusso, pseudocodice, linguaggio di programmazione) indicandone vantaggi e limiti.

Errori frequenti

  • Confondere il determinismo con la generalità: il primo riguarda l'univocità di ogni passo, la seconda l'applicabilità a un'intera classe di casi.
  • Ritenere algoritmo un procedimento che non garantisce la terminazione: senza la proprietà di finitezza non si ha un algoritmo, ma solo una procedura potenzialmente infinita.

Approfondimento

Conviene separare due nozioni di finitezza che spesso si confondono: la finitezza della descrizione (l'algoritmo è un testo di lunghezza finita, un numero finito di istruzioni) e la finitezza dell'esecuzione (per ogni input il calcolo termina dopo un numero finito di passi). Entrambe sono necessarie: un testo finito può descrivere un ciclo che non termina mai. Un procedimento che rispetta tutte le proprietà tranne la terminazione si dice semi-algoritmo o procedura, e non è un algoritmo. Il determinismo qui richiesto è quello degli algoritmi deterministici, in cui lo stato successivo è univocamente determinato dallo stato corrente; esistono però gli algoritmi randomizzati (probabilistici), che compiono scelte pseudo-casuali e la cui uscita o efficienza dipende dal caso — utilissimi in pratica, per esempio nel metodo Monte Carlo, ma da tenere distinti dal modello deterministico classico. La proprietà di eseguibilità si comprende appieno solo fissando l'esecutore e il suo repertorio finito di istruzioni elementari: ciò che è «passo elementare» per un calcolatore non lo è per una persona, e viceversa. Questa idea trova la sua formulazione rigorosa nella tesi di Church-Turing: la nozione intuitiva di «procedimento effettivo» coincide con ciò che è calcolabile da una macchina di Turing. È proprio tale tesi a fornire la definizione rigorosa di algoritmo — quella intuitiva delle quattro proprietà ne è la versione operativa — e sarà ripresa nel capitolo sulla teoria della computazione.

Ripasso attivo

Per ciascuna delle quattro proprietà fondamentali (finitezza, determinismo, generalità, eseguibilità), proponi un esempio di procedimento che la viola e spiega perché, di conseguenza, non può essere considerato un algoritmo.

Richiamo attivo

Ricorda i punti chiave — poi rivela.

Fonti: Indicazioni Nazionali per i Licei (DPR 89/2010, DM 211/2010) — Obiettivi Specifici di Apprendimento (Ministero dell'Istruzione e del Merito (MIM))

§ 03

Le strutture di controllo: sequenza, selezione, iterazione#

●●○StandardLPOSA-informatica-fondamenti-algoritmi — strutture di controllo fondamentali: sequenza, selezione, iterazione (teorema di Böhm-Jacopini)

Le tre strutture di controllo: sequenza, selezione, iterazione

Le tre strutture di controllofigura a più pannelli, 3 pannelli, Dati: Sequenza — Grafo, 3 nodi, 2 archi; Selezione — Grafo, 3 nodi, 2 archi; Iterazione — Grafo, 3 nodi, 3 archiLe tre strutture di controlloABCSequenzacond?A (vero)B (falso)VFSelezionecond?corpoesciVripetiFIterazione
Fig. 3Sequenza, selezione e iterazione: con queste tre strutture di controllo si costruisce ogni algoritmo (teorema di Böhm-Jacopini).

Punti chiave

Il teorema di Böhm-Jacopini (1966) stabilisce un risultato fondante: qualunque algoritmo può essere espresso utilizzando soltanto tre strutture di controllo elementari — la sequenza, la selezione e l'iterazione — combinate fra loro. È il fondamento teorico della programmazione strutturata, la metodologia, promossa anche da Edsger Dijkstra, che bandisce il salto incondizionato (goto) a favore di un flusso del controllo ordinato e leggibile.
La sequenza è la struttura più semplice: le istruzioni vengono eseguite una dopo l'altra, nell'ordine in cui sono scritte. La selezione (o struttura condizionale) sceglie quale blocco di istruzioni eseguire in base al valore di una condizione: nella forma a due rami (se condizione allora A altrimenti B) si esegue A se la condizione è vera, B se è falsa; esiste anche la forma a un ramo solo (senza altrimenti).
L'iterazione (o ciclo) ripete un blocco di istruzioni finché una condizione resta verificata. Si distinguono il ciclo a condizione iniziale (mentre condizione esegui blocco), che controlla la condizione prima di ogni ripetizione e può quindi non eseguire mai il blocco, e il ciclo a condizione finale (ripeti blocco finché condizione), che esegue il blocco almeno una volta. Quando il numero di ripetizioni è noto in anticipo si usa il ciclo enumerativo (per i da 1 a n).
Ogni ciclo deve garantire la terminazione: deve esistere una grandezza (il contatore o la condizione) che evolve a ogni iterazione fino a far cessare la ripetizione. Un ciclo il cui corpo non modifica mai le variabili della condizione di controllo è un ciclo infinito e viola la finitezza. La corretta combinazione di queste tre strutture — eventualmente annidate l'una nell'altra — è sufficiente a esprimere qualunque procedimento calcolabile.
S=∑i=1ni=n(n+1)2S = \sum_{i=1}^{n} i = \frac{n(n+1)}{2}S=i=1∑n​i=2n(n+1)​

Somma dei primi n interi

La somma accumulata dal ciclo enumerativo coincide con la formula chiusa di Gauss: un utile controllo di correttezza del risultato dell'iterazione.

Esempio svolto

Somma dei primi n interi con un ciclo enumerativo

Scrivi in pseudocodice un algoritmo che, dato un intero n > 0, calcoli e stampi la somma 1 + 2 + ... + n usando un ciclo enumerativo, e indica la grandezza che garantisce la terminazione.

  1. 01Inizializzazione

    Si pone una variabile accumulatore S a 0 prima del ciclo.

  2. 02Ciclo enumerativo

    Per i da 1 a n: S <- S + i. Il contatore i parte da 1 e cresce a ogni iterazione fino a n.

  3. 03Terminazione

    La grandezza che garantisce la terminazione è il contatore i: poiché aumenta di 1 a ogni passo e n è finito, dopo esattamente n iterazioni si ha i > n e il ciclo termina.

  4. 04Verifica con la formula di Gauss

    Per n = 5 il ciclo accumula 1+2+3+4+5 = 15; la formula chiusa conferma 5*6/2 = 15.

Risultato: leggi n; S <- 0; per i da 1 a n esegui S <- S + i; stampa S. Per n = 5 il risultato è 15, in accordo con n(n+1)/2.

Obiettivo Maturità

  • Saper enunciare il teorema di Böhm-Jacopini e spiegare perché le tre strutture di controllo sono sufficienti a costruire qualunque algoritmo (fondamento della programmazione strutturata).
  • Saper scegliere e applicare correttamente la struttura adatta (selezione vs iterazione; ciclo a condizione iniziale vs finale vs enumerativo) garantendo sempre la terminazione del ciclo.

Errori frequenti

  • Dimenticare di aggiornare, all'interno del corpo del ciclo, la variabile che compare nella condizione: il ciclo non termina mai (ciclo infinito).
  • Confondere il ciclo a condizione iniziale (mentre) con quello a condizione finale (ripeti...finché): il secondo esegue il corpo sempre almeno una volta, il primo può non eseguirlo affatto.

Approfondimento

Il fondamento della verifica di correttezza di un ciclo è l'invariante di ciclo: una proprietà che è vera immediatamente prima del ciclo e che, se vale all'inizio di un'iterazione, resta vera al termine della stessa. All'uscita, l'invariante combinato con la negazione della condizione di controllo fornisce la tesi da dimostrare. Per «S <- 0; per i da 1 a n: S <- S + i» l'invariante è «all'inizio dell'iterazione con contatore i, S contiene la somma 1+2+...+(i−1)»: è vero per i = 1 (S = 0, somma vuota), si conserva perché il corpo aggiunge proprio i, e all'uscita (i = n+1) dà «S = 1+2+...+n», cioè la correttezza cercata. Il teorema di Böhm-Jacopini non è solo un enunciato di esistenza ma è costruttivo: fornisce un procedimento per riscrivere qualunque diagramma di flusso, anche pieno di salti «goto», impiegando le sole tre strutture, eventualmente al prezzo di introdurre variabili di stato ausiliarie (flag booleane) che ricordano «a che punto siamo». È questo il motivo teorico per cui la programmazione strutturata non perde potere espressivo pur rinunciando al goto, salto che E. Dijkstra additò come fonte di codice illeggibile. Infine iterazione e ricorsione hanno lo stesso potere computazionale: ogni ciclo può essere riscritto come funzione ricorsiva e viceversa (quest'ultima con l'aiuto di una pila che simula i cicli annidati), un'equivalenza che sarà ripresa parlando di sottoprogrammi e ricorsione.

Ripasso attivo

Scrivi in pseudocodice un algoritmo che, dato un intero n > 0, calcoli e stampi la somma 1 + 2 + ... + n utilizzando un ciclo enumerativo; indica esplicitamente quale grandezza garantisce la terminazione.

Richiamo attivo

Ricorda i punti chiave — poi rivela.

Fonti: Indicazioni Nazionali per i Licei (DPR 89/2010, DM 211/2010) — Obiettivi Specifici di Apprendimento (Ministero dell'Istruzione e del Merito (MIM))

§ 04

Pseudocodice e diagrammi di flusso#

●●○StandardLPOSA-informatica-fondamenti-algoritmi — pseudocodifica e diagrammi di flusso (flowchart); variabili, costanti, espressioni

Diagramma di flusso: numero pari o dispari

Diagramma di flusso: pari o dispariGrafo, Inizio → leggi n, leggi n → n mod 2 = 0 ?, n mod 2 = 0 ? → pari, n mod 2 = 0 ? → dispari, pari → Fine, dispari → FineInizioleggi nn mod 2 = 0 ?paridispariFineVF
Fig. 4Legge n; se n mod 2 = 0 stampa «pari» (ramo vero), altrimenti «dispari» (ramo falso), poi termina.

Punti chiave

Per descrivere un algoritmo in modo preciso ma indipendente da uno specifico linguaggio di programmazione si usano due formalismi complementari. Lo pseudocodice è una notazione testuale che combina la chiarezza del linguaggio naturale con la struttura del codice: usa parole chiave fisse (leggi, scrivi, se...allora...altrimenti, mentre, per) e l'indentazione per evidenziare i blocchi, ma non è vincolato a una sintassi rigida.
Il diagramma di flusso (flowchart) è la rappresentazione grafica dell'algoritmo: ogni tipo di azione ha un simbolo convenzionale. L'ovale (o cerchio) indica inizio e fine; il parallelogramma le operazioni di ingresso/uscita (leggi, scrivi); il rettangolo le elaborazioni (assegnazioni, calcoli); il rombo le decisioni, da cui escono due rami etichettati Vero e Falso. Le frecce indicano il flusso del controllo, cioè l'ordine di esecuzione.
In entrambi i formalismi compaiono gli elementi base dell'elaborazione: le variabili, contenitori con un nome che custodiscono un valore modificabile; le costanti, valori fissi; e le espressioni, combinazioni di variabili, costanti e operatori (aritmetici, relazionali, logici) che producono un valore. L'assegnazione (di solito indicata con la freccia <-) attribuisce a una variabile il valore di un'espressione: x <- x + 1 calcola prima x + 1 e poi lo memorizza in x.
Pseudocodice e diagramma di flusso descrivono lo stesso algoritmo a livelli diversi: il flowchart è più immediato e visivo, utile per coglierne la struttura logica; lo pseudocodice è più compatto e si traduce quasi direttamente in un linguaggio di programmazione. Entrambi devono rispettare la programmazione strutturata, impiegando solo le tre strutture di controllo e mantenendo un unico punto di ingresso e un unico punto di uscita per ogni blocco.
Esempio svolto

Pseudocodice di un algoritmo con selezione

Scrivi lo pseudocodice di un algoritmo che legge un intero n e stampa «pari» se n è divisibile per 2, «dispari» altrimenti, coerente con il diagramma di flusso della Fig. 4.

  1. 01Ingresso

    leggi n (il dato di ingresso è un numero intero).

  2. 02Condizione di selezione

    Si calcola il resto della divisione intera di n per 2 con l'operatore modulo: la condizione è n mod 2 = 0.

  3. 03Rami della selezione

    se n mod 2 = 0 allora scrivi «pari» altrimenti scrivi «dispari».

  4. 04Verifica su un caso

    Per n = 7: 7 mod 2 = 1, diverso da 0, quindi si esegue il ramo altrimenti e si stampa «dispari» (corretto).

Risultato: leggi n; se n mod 2 = 0 allora scrivi «pari» altrimenti scrivi «dispari». Per n = 7 stampa «dispari».

Obiettivo Maturità

  • Saper tradurre un algoritmo dallo pseudocodice al diagramma di flusso e viceversa, usando correttamente i simboli convenzionali (ovale, parallelogramma, rettangolo, rombo).
  • Saper leggere e scrivere espressioni e assegnazioni, comprendendo che l'assegnazione x <- x + 1 valuta prima il membro destro e poi aggiorna la variabile.

Errori frequenti

  • Usare il simbolo sbagliato nel flowchart: per esempio un rettangolo (elaborazione) per una decisione, che invece richiede il rombo con due rami etichettati.
  • Interpretare l'assegnazione come un'uguaglianza matematica: x <- x + 1 non è un'equazione impossibile, ma l'istruzione «aumenta x di 1»; confondere = (confronto) con <- (assegnazione) è un errore tipico.

Approfondimento

Lo strumento principe per verificare a mano un algoritmo, prima ancora di eseguirlo su un calcolatore, è la tabella di traccia (desk check o dry run): si predispone una colonna per ogni variabile e una riga per ogni passo, e si aggiornano i valori istruzione per istruzione, simulando l'esecutore. Così si scoprono gli errori logici — un contatore che parte dal valore sbagliato, una condizione invertita — che nessun controllo puramente sintattico rivelerebbe. La distinzione fra sintassi e semantica è qui cruciale: la sintassi è l'insieme delle regole di forma (come si scrive un'istruzione), la semantica è il significato, cioè l'effetto sull'esecutore. L'assegnazione «x <- espressione» ha semantica di effetto sullo stato: prima valuta il membro destro nello stato corrente, poi vi memorizza il risultato distruggendo il valore precedente; per questo «x <- x + 1» non è l'uguaglianza impossibile «x = x + 1», ma l'istruzione «incrementa x di 1». Un formalismo alternativo al diagramma di flusso è il diagramma strutturato di Nassi-Shneiderman, che rappresenta l'algoritmo come blocchi annidati anziché come nodi collegati da frecce: poiché non esistono frecce libere, i salti sono impossibili per costruzione e la struttura a blocchi della programmazione strutturata risulta immediatamente leggibile. Ogni buona pseudocodifica rispetta inoltre la regola dell'unico ingresso e unica uscita per ciascun blocco, che rende l'algoritmo componibile e verificabile pezzo per pezzo.

Ripasso attivo

Disegna il diagramma di flusso e scrivi lo pseudocodice di un algoritmo che legge un numero intero e stampa la parola «pari» se è divisibile per 2, «dispari» altrimenti.

Richiamo attivo

Ricorda i punti chiave — poi rivela.

Fonti: Indicazioni Nazionali per i Licei (DPR 89/2010, DM 211/2010) — Obiettivi Specifici di Apprendimento (Ministero dell'Istruzione e del Merito (MIM))

§ 05

Cenni a correttezza ed efficienza#

●●●ApprofondimentoLPOSA-informatica-fondamenti-algoritmi — cenni alla complessità e all'efficienza di un algoritmo (correttezza, numero di operazioni)

Crescita del numero di confronti: ricerca lineare (~n) e ricerca binaria (~log2 n)

Costo a confronto: lineare vs logaritmicoGrafico di ricerca lineare ~ n, crescente, nell’intervallo x da 1 a 64, Grafico di ricerca binaria ~ log2 n, zeri in x = 1, crescente, nell’intervallo x da 1 a 6410203040506010203040506064 confronti6 confrontiricerca lineare~ nricerca binaria~ log2 nnumero di confrontidimensione n dell'input

Punti chiave

Un algoritmo non basta che termini: deve essere corretto, cioè produrre l'output giusto per ogni input ammissibile, in accordo con la specifica del problema. La correttezza si argomenta verificando che l'algoritmo si comporti bene nei casi tipici e, soprattutto, nei casi limite (input vuoto, valore nullo, valore minimo o massimo): è proprio sui casi limite che gli algoritmi apparentemente giusti falliscono più spesso.
Accertata la correttezza, ci si chiede quanto l'algoritmo sia efficiente, cioè quante risorse consumi. L'efficienza si valuta principalmente in termini di tempo (numero di operazioni elementari eseguite) e di spazio (memoria occupata). Per non dipendere dalla velocità della macchina, si conta il numero di operazioni fondamentali in funzione della dimensione n dell'input, ottenendo una stima indipendente dall'hardware.
Lo stesso problema può ammettere algoritmi con efficienza molto diversa. Cercare un elemento in una sequenza di n dati con la ricerca lineare richiede, nel caso peggiore, n confronti: il costo cresce proporzionalmente a n (costo lineare). Se i dati sono ordinati, la ricerca binaria dimezza a ogni passo lo spazio di ricerca e richiede circa log2(n) confronti (costo logaritmico), molto più conveniente per n grande.
Per confrontare gli algoritmi si distingue il caso migliore, il caso peggiore e il caso medio, e ci si concentra di norma sul caso peggiore, che garantisce un limite superiore al costo. L'ordine di grandezza del numero di operazioni (costante, logaritmico, lineare, quadratico, esponenziale...) descrive come il costo cresce all'aumentare di n e costituisce il criterio principale per scegliere, fra più algoritmi corretti, quello da preferire.
Clinpeggiore=nC_{\text{lin}}^{\text{peggiore}} = nClinpeggiore​=n

Ricerca lineare (caso peggiore)

Nel caso peggiore (elemento assente o in ultima posizione) la ricerca lineare confronta x con tutti gli n elementi: il costo cresce linearmente con n.

Cbin≈⌊log⁡2n⌋+1C_{\text{bin}} \approx \lfloor \log_2 n \rfloor + 1Cbin​≈⌊log2​n⌋+1

Ricerca binaria (dati ordinati)

Dimezzando a ogni passo lo spazio di ricerca, il numero di confronti cresce come il logaritmo in base 2 di n: per n = 1000 sono circa 10 confronti contro i 1000 della ricerca lineare.

Esempio svolto

Costo della ricerca lineare e confronto con la binaria

Scrivi la ricerca lineare di un valore x in una sequenza di n elementi, determina il numero di confronti nel caso peggiore e confrontalo con la ricerca binaria su dati ordinati per n = 1000.

  1. 01Algoritmo (pseudocodice)

    trovato <- falso; per i da 1 a n esegui: se A[i] = x allora trovato <- vero. Si scorre l'intera sequenza confrontando ogni elemento con x.

  2. 02Caso peggiore della ricerca lineare

    Se x non è presente (o è l'ultimo elemento), si eseguono n confronti: il costo è proporzionale a n.

  3. 03Costo della ricerca binaria

    Su dati ordinati la ricerca binaria dimezza lo spazio a ogni passo: il numero di confronti è circa il logaritmo in base 2 di n.

  4. 04Confronto numerico per n = 1000

    Lineare: fino a 1000 confronti. Binaria: log2(1000) ~ 9.97, quindi circa 10 confronti. La binaria è circa cento volte più conveniente, ma richiede dati ordinati.

Risultato: La ricerca lineare costa fino a n = 1000 confronti nel caso peggiore; la ricerca binaria ne richiede circa 10 (~log2 1000), risultando nettamente più efficiente sui dati ordinati.

Obiettivo Maturità

  • Saper distinguere la correttezza (produce l'output giusto) dall'efficienza (consuma poche risorse) e argomentare la correttezza esaminando i casi limite.
  • Saper stimare il costo di un algoritmo contando le operazioni in funzione di n e confrontare algoritmi diversi (ricerca lineare ~n vs ricerca binaria ~log2 n).

Errori frequenti

  • Misurare l'efficienza con il tempo in secondi misurato su una macchina specifica: tale valore dipende dall'hardware e non confronta gli algoritmi; va contato invece il numero di operazioni in funzione di n.
  • Trascurare i casi limite (sequenza vuota, n = 0, elemento assente) nel valutare la correttezza: un algoritmo corretto sui casi «normali» può fallire proprio lì.

Approfondimento

La nozione intuitiva di «ordine di grandezza» si formalizza con la notazione O-grande (big-O), che descrive il comportamento asintotico del costo per n grande. Si scrive «f(n) = O(g(n))» quando esistono una costante «c > 0» e una soglia «n₀» tali che «f(n) ≤ c·g(n)» per ogni «n ≥ n₀»: g(n) è allora un limite superiore alla crescita di f, a meno di un fattore costante. Da questa definizione discende perché si trascurino le costanti moltiplicative e i termini di ordine inferiore: «3n² + 5n + 7» è «O(n²)», perché per n grande il termine quadratico domina. Accanto a O (limite superiore) si usano «Ω» (limite inferiore) e «Θ» (ordine esatto, quando O e Ω coincidono). La gerarchia degli ordini più comuni è «O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ)», e passare da un ordine al successivo cambia radicalmente la scalabilità del programma. Il costo logaritmico della ricerca binaria si ricava dalla sua equazione di ricorrenza: a ogni passo il problema si dimezza al prezzo di un confronto, cioè «T(n) = T(n/2) + O(1)», che sviluppata dà «T(n) = O(log₂ n)» — dopo circa «log₂ n» dimezzamenti l'intervallo si riduce a un solo elemento. Resta il compromesso di fondo: la ricerca binaria è velocissima ma esige dati ordinati, e ordinare costa a sua volta almeno «O(n log n)»; conviene quindi solo quando la stessa sequenza, ordinata una volta, viene poi interrogata molte volte.

Ripasso attivo

Per una sequenza di n elementi, scrivi lo pseudocodice della ricerca lineare di un valore x, conta il numero di confronti nel caso peggiore e confrontalo con il costo della ricerca binaria su dati ordinati per n = 1000.

Richiamo attivo

Ricorda i punti chiave — poi rivela.

Fonti: Indicazioni Nazionali per i Licei (DPR 89/2010, DM 211/2010) — Obiettivi Specifici di Apprendimento (Ministero dell'Istruzione e del Merito (MIM))

Contenuti

Sezione -- / 05

    • 01Dal problema all'algoritmo: analisi e modellizzazione○
    • 02Proprietà degli algoritmi e formalismi di rappresentazione◐
    • 03Le strutture di controllo: sequenza, selezione, iterazione◐
    • 04Pseudocodice e diagrammi di flusso◐
    • 05Cenni a correttezza ed efficienza●

0/5 Letti

Dagli appunti all'allenamento

Algoritmi, problem solving e pseudocodifica

Consolida questo argomento con domande dalla banca dati.

~24
min
3
Competenze
Esercitati

Riferimenti e fonti

Fonti

Ministero dell'Istruzione e del Merito (MIM)

  • Indicazioni Nazionali per i Licei (DPR 89/2010, DM 211/2010) — Obiettivi Specifici di Apprendimento

Argomento successivo

Linguaggi di programmazione e sintassi

EuraStudy·Appunti T·01·MMXXVI

Continua con l'argomento successivo: il percorso viene conservato.