Lo pseudocodice per la scrittura di algoritmi: un metodo efficace anche nella didattica per le disabilità visive

Tempo di lettura: 7 minuti

Oggi vi parlo di algoritmi e pseudocodice, in un ottica un po’ diversa dal solito. Ho conosciuto questi termini durante gli studi tecnici come perito informatico, capendone le potenzialità come utente ipovedente. Ne riconosco l’efficacia ancora oggi da non vedente e rilancio dichiarando che per una persona con disabilità visiva, la tecnica della scrittura di pseudocodice è assolutamente efficace, rappresentando comunque una metodologia usata spesso anche da sviluppatori normodotati. Quindi non è un metodo esclusivo, ma una tecnica nata per tutti che nello specifico ci è molto utile.

Una definizione di algoritmo

Wikipedia ci fornisce una definizione di algoritmo chiara e concisa: “Un algoritmo è un procedimento che risolve un determinato problema attraverso un numero finito di passi elementari, chiari e non ambigui.”. Cosa aggiungere di altro?
Nel campo informatico e in particolare nel mondo della programmazione, la definizione di algoritmo ci è utile per la risoluzione di varie tipologie di problemi. Infatti, i passi necessari alla risoluzione logica di un dato problema, possono essere convertiti in una sequenza di istruzioni elementari, ordinate, non ambigue e finite.
La capacità di definire tali passi e la conoscenza approfondita degli stessi è chiamato “pensiero computazionale”.
In una fase successiva, tali istruzioni, saranno convertite utilizzando la sintassi del linguaggio di programmazione scelto in fase di progettazione.

Un esempio preso dalla vita reale

Potrei proporvi un esempio che appartiene strettamente al mondo della matematica, ma preferisco parlarvi di qualcosa di manuale che fa parte, quasi certamente, della nostra quotidianità. Infatti, ogni giorno, quando compiamo azioni o attività, inconsciamente, utilizziamo degli algoritmi per portarle a termine, tramite una metodologia a noi nota, quella secondo noi più adatta per raggiungere il risultato finale.
Avete mai pensato ai passi necessari e ordinati per preparare una tazza di caffè con una moka?
Seppur con delle piccole variazioni, potremmo ipotizzare i seguenti passi:

  1. prendo la moka;
  2. la svito ;
  3. lavo la moka sotto l’acqua corrente;
  4. riempio il serbatoio dell’acqua in base a quanto voglio intenso il caffè;
  5. inserisco il filtro che conterrà il caffè;
  6. prendo il barattolo del caffè macinato;
  7. con un cucchiaino, riempio il filtro tanto quanto basta per avere un caffè più o meno forte;
  8. avvito la moka;
  9. ripongo la moka chiusa sul fornello ancora spento;
  10. accendo il fuoco e regolo la fiamma;
  11. attendo che il caffè sia pronto;
  12. spengo il fuoco;
  13. prendo una tazza;
  14. verso il caffè nella tazza;
  15. ripongo la moka.

Se ci siamo chiesti il motivo per cui sappiamo preparare un caffè, una risposta possibile è che l’esperienza nel prepararlo, magari ogni mattina per colazione, ci ha fatto migliorare nei passi necessari, moderando la quantità di caffè, lo prepariamo per soddisfare meglio i nostri gusti, mettendo più o meno acqua, ne gestiamo l’intensità. Naturalmente, il nostro risultato finale è il caffè stesso, del quale sappiamo indicare un indice di gradimento ed in base ad esso, la prossima volta, cercheremo di migliorarlo.
Ci capiterà spesso di avere definito una soluzione che crediamo ottimale, per poi accorgerci che ciò che avevamo dedotto era assolutamente migliorabile. Il bello è che potremo migliorare il nostro algoritmo, rendendolo più funzionale, questa prende il nome di fase di ottimizzazione.

Lo pseudocodice

Lo pseudocodice (o pseudocodifica) è una modalità testuale per la rappresentazione di un algoritmo. Tale linguaggio intermedio, non rispetta degli standard definiti da enti preposti e rappresenta il passo precedente alla scrittura vera e propria delle istruzioni in un linguaggio macchina. Anche lo pseudocodice, come i linguaggi veri e propri, deve rispettare una sintassi e delle regole che proveremo a definire.
Quando si raggiunge una certa esperienza nel campo della programmazione, lo pseudocodice torna utile per prendere appunti sulla logica che dovrà avere una certa porzione di codice, è un modo di scrivere universale, chiaro e utile anche ad altri sviluppatori con cui si condivide il lavoro.

Un primo semplice esempio

Senza darvi altre indicazioni teoriche, proviamo a scrivere l’algoritmo che determina se un numero è pari o dispari, tramite il seguente pseudocodice:

  1. INIZIO
  2. Scrivi: “Inserisci un numero naturale n”
  3. Leggi n dall’utente
  4. Se n%2 è = 0 (se il resto della divisione per 2 è 0) ALLORA:
    1. Scrivi: “Il numero è pari”
  5. Altrimenti:
    1. Scrivi: “Il numero è dispari”
  6. FINE SE
  7. FINE

Prestate attenzione al comando “LEGGI n”, infatti esso introduce un concetto fondamentale, quello di variabile. L’elemento n è un contenitore di un certo dato, tale contenitore rimane immutato fino a che non diamo un comando che ne alteri il contenuto. L’abbiamo chiamato n, ma lo potevamo anche chiamare diversamente, ad esempio numero o x, siamo noi a decidere questi nomi.
Come potete vedere, questo linguaggio è più rigoroso rispetto a quello utilizzato per l’algoritmo per la preparazione del caffè. Vengono di certo rispettate delle regole e viene utilizzata una specifica sintassi.
Questa metodologia testuale,è assolutamente accessibile ed utilizzabile da non vedenti e ipovedenti. Si integra in modo ottimale con il lettore di schermo,perchè la sintassi la si può scrivere in un qualsiasi editor di testo e non presenta alcun riferimento grafico.
L’unico passaggio necessario richiesto, è quello di pensare a step, quando si affronta la risoluzione di un problema. Molti di noi già lo fa, senza rendersene conto.
Posso suggerire di iniziare con l’aprire il Blocco Note o un qualsiasi editor di testo e iniziare a elencare i passi necessari alla risoluzione del dato problema. Scriveteli in un linguaggio non formale, ma descrittivo.
Successivamente, accertatevi che gli step siano ordinati in senso logico e non preoccupatevi di eventuali step ripetuti, infatti vedremo come “riciclare” degli step già definiti, in modo da normalizzare il flusso del nostro algoritmo.
Se sono invece presenti passaggi che contengono più operazioni, bisogna cercare di separarli, creando così più step, in modo che sia più semplice convertirli in linguaggio macchina.
Fatto ciò, si può passare alla fase di conversione nel linguaggio di pseudocodifica e solo successivamente convertiremo il tutto nel linguaggio di programmazione scelto.

Definiamo un nostro standard

Nel definire un nostro standard, dobbiamo sempre tenere conto delle istruzioni che un linguaggio di programmazione ci mette a disposizione. Non dobbiamo inoltre dimenticare che un algoritmo, rappresentato tramite lo pseudocodice, dovrebbe poter essere tradotto in qualsiasi linguaggio di programmazione e non solo in quello che vogliamo utilizzare

Definiamo il seguente standard e utilizziamolo per i nostri algoritmi:

  • INIZIO : punto di inizio del nostro algoritmo;
  • FINE : termine del nostro algoritmo;
  • SCRIVI “stringa” o variabile : output, leggibile dall’utente;
  • LEGGI variabile : input inserito dall’utente;
  • VARIABILE = valore, espressione o procedura : assegna un valore ad una data variabile. Tale valore può essere fisso, come un numero o una stringa, oppure può derivare da un’espressione o dall’esecuzione di una procedura. Ciò che definiamo a destra dell’uguale, verrà assegnato al contenitore a sinistra dell’uguale;
  • + : operatore aritmetico di somma;
  • – : operatore aritmetico di sottrazione;
  • * : operatore aritmetico di prodotto;
  • / : operatore aritmetico di divisione;
  • % : operatore per avere il modulo tra due numeri, cioè il resto della divisione tra i due numeri;
  • = : operatore aritmetico usato per assegnare un risultato o un valore;
  • ! : simbolo usato per negare un valore o condizione. Da scrivere prima del valore, condizione o espressione da negare;
  • != : operatore utilizzato per indicare che un valore o condizione è diversa da qualcos’altro;
  • == : operatore usato nelle condizioni per indicare una uguaglianza in un confronto;
  • < o > : simbolo di minore e maggiore, usati per confrontare i valori nelle condizioni dei vari costrutti condizionali o cicli condizionati;
  • e : usata come una congiunzione, si utilizza per unire più condizioni, indicando così che devono essere entrambe soddisfatte per validare la condizione;
  • o : utilizzata come oppure, indica che tra due condizioni, basta che ne sia valida una per validare il confronto;
  • Se (condizione) ALLORA {istruzione1} ALTRIMENTI {istruzione2} FINE SE : questa sintassi rappresenta un controllo condizionale, di certo uno dei più utilizzati per definire la logica di un algoritmo. Questo tipo di istruzioni possono essere annidate per aumentare la complessità dei controlli sulle condizioni. Ad esempio, si può inserire un ulteriore SE all’interno del ramo ALTRIMENTI, creando così una serie annidata di controlli condizionali;
  • FINCHÉ (condizione) RIPETI {istruzioni} FINE FINCHÉ : fino a che una data condizione è verificata, ripeti le istruzioni. Questa sintassi definisce ciò che è chiamato ciclo condizionato;
  • RIPETI {istruzioni} FINCHÉ (condizione) FINE RIPETI : ripeti le istruzioni fino a che una data condizione è verificata. Anche questa sintassi esprime il concetto di ciclo condizionato, con la differenza che le istruzioni vengono eseguite almeno una volta per poi ripetersi se la condizione è ancora soddisfatta;
  • RICHIAMA PROCEDURA() : invoca una data procedura, richiamandola per nome, utile anche per il riuso di porzioni di codice ripetute. A livello teorico si rimanda al concetto di ricorsione;
  • PROCEDURA(parametri) {istruzioni}RITORNO (valore) FINE PROCEDURA: una procedura contiene una porzione di codice, solitamente riutilizzabile ed invocabile nel flusso dell’algoritmo. Una procedura può ricevere dei parametri quando invocata e può ritornare al chiamante un valore.

Queste sono le istruzioni principali. Non dimentichiamo che nello scrivere la nostra pseudocodifica, è consigliabile anteporre ad ogni istruzione un numero che ne indichi l’ordinamento, proprio come descritto nell’esempio per l’individuazione dei numeri pari e dispari. Numerare le istruzioni ci serve per capire la struttura dell’algoritmo, soprattutto quando ci troviamo ad utilizzare la sintassi per i costrutti condizionali o i cicli. In alternativa alla numerazione, possiamo incolonnare la pseudocodifica, utilizzando i rientri di riga, tecnica che prende il nome di indentazione del codice, solitamente si utilizzano le tabulazioni, tasto “tab”. Così sarà semplice ed intuitivo incolonnare i blocchi di istruzione sotto al costrutto di appartenenza.
Potremmo definire una pseudocodifica più dettagliata e rigorosa, ma secondo me, con questi costrutti di base, possiamo scrivere con chiarezza tutti gli algoritmi di cui avremo bisogno.
Se capiamo questo approccio, avremo ben chiara la logica dell’algoritmo e tradurre il tutto in un linguaggio macchina sarà semplice.
Questa metodologia è anche molto comoda per testare in modo rapido la logica del nostro flusso di istruzioni. Infatti possiamo prevedere diversi casi in cui cambiando i valori dati in ingresso avremo diversi risultati finali che dovranno rispettare le condizioni del nostro algoritmo. Se questi test dovessero fallire, sarebbe inutile concentrarsi nello scrivere il codice macchina, varrebbe la pena prima dedicarsi alla stesura di uno pseudocodice funzionante.

In conclusione

Abbiamo visto cosa si intende per algoritmo e come lo si converte in uno pseudocodice ben definito. Il passo successivo che rimane da compiere è la traduzione dello stesso in un linguaggio di programmazione. Non ho inventato io questi metodi, ho semplicemente preso spunto dal mio vissuto e penso che questa metodologia, applicata alla disabilità visiva, possa aiutare per ottenere ottimi risultati nella risoluzione di qualsiasi tipo di problema. Molto di ciò che le persone normodotate fanno con la vista, noi lo dobbiamo fare con la mente, dobbiamo avere dei pensieri ben ordinati, ridotti ai minimi termini, la logica del flusso di un listato di codice deve essere disegnata nella nostra mente ed io utilizzo questo metodo semplice e potente.

Materiale e esercizi proposti

  • provare a riscrivere l’algoritmo della moka con la pseudocodifica. Immaginatelo come un flusso in cui vengono date delle istruzioni all’utente tramite il comando “SCRIVI” e vengono inseriti dall’utente ingredienti tramite “LEGGI”;
  • scrivere una seconda versione dell’algoritmo della moka, implementando delle situazioni particolari. Ad esempio l’assenza di caffè, senza il quale non potremmo preparare la bevanda. In questo modo potrete utilizzare il costrutto condizionale “SE …”. Potete inventare voi delle nuove situazioni da gestire e controllare;
  • progettare una calcolatrice per effettuare le 4 operazioni fondamentali (addizione, sottrazione, moltiplicazione e divisione). È un progetto apparentemente semplice, ma presenta delle piccole insidie dovute alle proprietà fondamentali di queste potenti operazioni. Supponiamo che i numeri inseriti in input siano interi positivi >= 0 (l’insieme dei numeri naturali). Progettate voi liberamente la logica, le fasi di input e output e tutti i controlli da effettuare sui numeri inseriti e sulla fattibilità delle operazioni;
  • Implementazione di algoritmi materiale online libero su Wiki Books: una volta impratichiti nell’analisi di un problema e capiti i concetti per la stesura di uno pseudocodice, potrete sbizzarrirvi nell’analizzare gli algoritmi proposti, progettandoli e scrivendoli a modo vostro e confrontando le soluzioni proposte. Consiglio di iniziare con l’algoritmo per l’elevazione a potenza e con l’algoritmo di Euclide. Man mano che si andrà avanti con gli studi, si riusciranno a risolvere anche quelli più complessi.