martedì 3 febbraio 2026

Corso Pensiero Computazionale e Coding per Tutti: 3 Il linguaggio binario e i sistemi di numerazione

3 Il linguaggio binario e i sistemi di numerazione

Introduzione: perché il binario?

Immagina un corridoio pieno di lampadine. Ogni lampadina può essere accesa (1) o spenta (0). Con una sola lampadina puoi indicare due stati: acceso/spento. Con due lampadine hai quattro combinazioni (00, 01, 10, 11). Questo è il cuore del linguaggio digitale: segnali ON/OFF, sì/no, 1/0. I computer parlano così perché i componenti elettronici — transistor, porte logiche — funzionano scegliendo tra due stati.

Concetti teorici essenziali

  • Bit = binary digit = 0 o 1.
  • Posizione in un numero binario corrisponde a una potenza di 2. Da destra a sinistra: 2⁰, 2¹, 2², 2³, …
  • Byte = 8 bit. Nibble = 4 bit. Parole (word) dipendono dall’architettura (16, 32, 64 bit).
  • Range valori: con n bit si rappresentano 0 … (2ⁿ − 1) per numeri senza segno.
  • Due-complemento = convenzione per rappresentare numeri negativi (vedremo come funziona).

Tabella rapida potenze di 2 (utile come "tassello" in classe)

  • 2⁰ = 1
  • 2¹ = 2
  • 2² = 4
  • 2³ = 8
  • 2⁴ = 16
  • 2⁵ = 32
  • 2⁶ = 64
  • 2⁷ = 128
  • 2⁸ = 256

Conversioni — esempi passo-passo (eseguiti digit-by-digit)

A) Da binario a decimale — Esempio: 1011

Leggiamo da sinistra (ma calcoliamo per posizione da destra a sinistra):

  • cifre (da sinistra a destra): 1 0 1 1
  • posizioni (da destra): 2³, 2², 2¹, 2⁰ = 8, 4, 2, 1
    Calcolo:
  • 1 × 2³ = 1 × 8 = 8
  • 0 × 2² = 0 × 4 = 0
  • 1 × 2¹ = 1 × 2 = 2
  • 1 × 2⁰ = 1 × 1 = 1
    Somma = 8 + 0 + 2 + 1 = 11 (decimale).

B) Da decimale a binario — Metodo divisione per 2 (resti)

Esempio: convertiamo 156 in binario (mostro ogni divisione: quoziente e resto).

  • 156 ÷ 2 = 78 resto 0
  • 78 ÷ 2 = 39 resto 0
  • 39 ÷ 2 = 19 resto 1
  • 19 ÷ 2 = 9 resto 1
  • 9 ÷ 2 = 4 resto 1
  • 4 ÷ 2 = 2 resto 0
  • 2 ÷ 2 = 1 resto 0
  • 1 ÷ 2 = 0 resto 1 (qui terminiamo)
    Ora leggiamo i resti dal basso verso l’alto: 1 0 0 1 1 1 0 010011100 (binario). Verifica: 128 + 0 + 0 + 16 + 8 + 4 + 0 + 0 = 156.

C) Da decimale a esadecimale (base 16) — esempio: 255

Divisione per 16:

  • 255 ÷ 16 = 15 resto 15 → 15 in esadecimale è F
  • 15 ÷ 16 = 0 resto 15F
    Quindi 255 decimale = FF (esadecimale).

Codifica di caratteri: ASCII (pratica)

I computer memorizzano lettere come numeri. ASCII standard associa ad esempio:

  • "A" → 65 → in binario 01000001 (8 bit).
    Esempio pratico: trasformiamo la parola Tom (passo-passo):
  • T = 84 → dividendo per 2 otteniamo binario: 01010100
  • o = 111 → binario: 01101111
  • m = 109 → binario: 01101101
    Nome in binario: 01010100 01101111 01101101.

(Se vuoi, puoi fornire la tabella ASCII da stampare; per la lezione basta mostrare qualche esempio e far convertire i padroni di casa.)

Operazioni binarie — esempi svolti

A) Addizione binaria — esempio: 1011 + 1101

Allineiamo a destra:

   1011   (11 decimale)
 + 1101   (13 decimale)
 ------

Sommiamo colonna per colonna da destra:

  • colonna 0 (2⁰): 1 + 1 = 2 → scrivo 0, porto 1 (carry).
  • colonna 1 (2¹): 1 + 0 + carry1 = 2 → scrivo 0, porto 1.
  • colonna 2 (2²): 0 + 1 + carry1 = 2 → scrivo 0, porto 1.
  • colonna 3 (2³): 1 + 1 + carry1 = 3 → 3 in binario è 1 con carry 1 (perché 3 = 1 + 2). Scrivo 1, porto 1.
  • carry finale = 1 → lo scrivo a sinistra.

Risultato: 11000.

Verifica in decimale: 11 + 13 = 24 → 11000 in binario = 16 + 8 = 24. Perfetto.

B) Sottrazione con due-complemento — esempio: 13 − 5 (usando 8 bit)

Rappresentazioni (8 bit):

  • 13 = 00001101
  • 5 = 00000101
    Passi per ottenere −5 in due-complemento:
  1. inverti tutti i bit di 5: 11111010
  2. aggiungi 1: 11111010 + 1 = 11111011 (questo è il −5 in due-complemento)
    Ora addiziona 13 + (−5):
  00001101
+ 11111011
= 00001000 (con carry che scarta)

Risultato 00001000 = 8. Corretto.

C) Esempio di overflow (8 bit): 130 + 140

  • 130 = 10000010
  • 140 = 10001100
    Addizione:
  • Somma aritmetica: 130 + 140 = 270
  • In 8 bit il massimo è 255 → abbiamo overflow. Se consideriamo solo gli 8 bit di basso peso otteniamo 00001110 = 14.
    Spiegazione: la somma genera un carry oltre l’ottavo bit, perso se si lavora su 8 bit senza segnalazione → valore risultante = 270 mod 256 = 14.

Esercizi svolti

Esercizio 1 — Converti 19 in binario (passi)

Divisioni:

  • 19 ÷ 2 = 9 r 1
  • 9 ÷ 2 = 4 r 1
  • 4 ÷ 2 = 2 r 0
  • 2 ÷ 2 = 1 r 0
  • 1 ÷ 2 = 0 r 1
    Rivolgi i resti: 10011. Verifica: 16 + 0 + 0 + 2 + 1 = 19.

Esercizio 2 — Usa ASCII: quale è il binario di "C"?

"C" = 67 decimale. Convertiamo:

  • 67 ÷ 2 = 33 r 1
  • 33 ÷ 2 = 16 r 1
  • 16 ÷ 2 = 8 r 0
  • 8 ÷ 2 = 4 r 0
  • 4 ÷ 2 = 2 r 0
  • 2 ÷ 2 = 1 r 0
  • 1 ÷ 2 = 0 r 1
    Resta: 1000011. Con 8 bit (prefisso aggiunto): 01000011.

Esercizio 3 — Addizione: 0110 + 0011

  • 0110 (6) + 0011 (3) = 1001 (9). Passaggi: colonna per colonna, portando eventuali carry (qui nessuno tranne al limite).

Test finale (autovalutazione)

1. Converti in binario:
a) 6 →
b) 13 →
c) 31 →

2. Qual è il valore decimale di 10110?
a) 22 b) 23 c) 21 d) 24

3. Qual è il codice ASCII della lettera C?
a) 65 b) 67 c) 66 d) 68

4. In esadecimale, qual è il simbolo per il valore decimale 15?
a) E b) D c) F d) G

5. Quale rappresentazione binaria è corretta per il numero 9?
a) 1001 b) 1011 c) 0110 d) 1111

10) Soluzioni del test — con spiegazioni passo-passo

1. Converti in binario
a) 6 → divisioni: 6 ÷ 2 = 3 r0; 3 ÷ 2 = 1 r1; 1 ÷ 2 = 0 r1 → leggendo i resti: 110.
b) 13 → 13 ÷ 2 = 6 r1; 6 ÷ 2 = 3 r0; 3 ÷ 2 = 1 r1; 1 ÷ 2 = 0 r1 → resti: 1101.
c) 31 → 31 ÷ 2 = 15 r1; 15 ÷ 2 = 7 r1; 7 ÷ 2 = 3 r1; 3 ÷ 2 = 1 r1; 1 ÷ 2 = 0 r1 → 11111.

2. 10110 → valore decimale
Calcolo posizioni: da destra 2⁰=1, 2¹=2, 2²=4, 2³=8, 2⁴=16
Cifre: 1·16 + 0·8 + 1·4 + 1·2 + 0·1 = 16 + 0 + 4 + 2 + 0 = 22 → risposta a).

3. ASCII di C
A è 65, B 66, C 67 → risposta b). (In binario C = 01000011.)

4. Valore decimale 15 in esadecimale
In esadecimale i simboli 10–15 corrispondono a A–F; quindi 15 → F → risposta c).

5. Rappresentazione binaria del 9
9 = 8 + 1 = 2³ + 2⁰ → cifre 1001 → risposta a).


lunedì 2 febbraio 2026

Corso Pensiero Computazionale e Coding per Tutti: 2 Coding unplugged: attività senza computer

 
2 Coding unplugged: attività senza computer

Introduzione: Cos’è il coding unplugged e perché è così efficace

Immagina di poter insegnare ai bambini e ai ragazzi i concetti fondamentali della programmazione senza accendere nemmeno un computer. Può sembrare incredibile, ma è proprio questo che fa il coding unplugged: utilizza giochi, attività manuali, simulazioni e materiali semplici per far comprendere come funziona il pensiero computazionale.

Questo approccio è efficace perché:

  • Rende visibili concetti astratti come algoritmi, cicli, condizioni e sequenze logiche attraverso attività pratiche e corporee.
  • Coinvolge tutto il corpo, sviluppando anche la coordinazione motoria, la lateralità, la capacità di previsione e la collaborazione.
  • È perfetto per tutte le età, dalla scuola dell’infanzia fino alla secondaria, perché permette di adattare la complessità e l’astrazione.
  • Permette di lavorare sul ragionamento e sulla risoluzione dei problemi senza distrazioni tecnologiche, concentrandosi sul cuore della programmazione: la logica.

Cos’è un algoritmo? Una definizione semplice e pratica

Spesso sentiamo parlare di algoritmo come una cosa complicata. In realtà, un algoritmo è semplicemente una serie di istruzioni ordinate, cioè un “programma” che dice passo dopo passo cosa fare per raggiungere un obiettivo.

Per esempio, pensa a come preparare una tazza di tè:

  1. Prendi una tazza pulita.
  2. Metti un filtro con la bustina di tè nella tazza.
  3. Versa acqua calda.
  4. Aspetta 3 minuti.
  5. Rimuovi il filtro.
  6. Aggiungi zucchero se vuoi.

Questo è un algoritmo! È un insieme di istruzioni che deve essere seguito in sequenza per ottenere il risultato desiderato.

🔧 Attività pratiche unplugged

1. Programmare un compagno per uscire da un labirinto

Disegna su un foglio o a terra un labirinto semplice con caselle quadrate (tipo una griglia 5x5).

Obiettivo: Un partecipante è il “robot”, gli altri sono programmatori che gli danno istruzioni per uscire dal labirinto.

  • Le istruzioni possibili sono: Avanti, Indietro, Giro a sinistra, Giro a destra.
  • Il “robot” deve eseguire le istruzioni esattamente nell’ordine dato, senza interpretazioni.
  • I programmatori scrivono la sequenza di passi (algoritmo) prima che il robot inizi.

Esempio svolto:

Supponiamo che il robot parta dalla casella in alto a sinistra e che la via per uscire sia:

  • Avanti
  • Avanti
  • Giro a destra
  • Avanti
  • Giro a sinistra
  • Avanti

Dopo aver scritto la sequenza, il robot la segue e raggiunge l’uscita.

2. Giochi con frecce direzionali, tessere e dadi logici

Distribuisci ai partecipanti tessere con frecce (⬆️⬇️⬅️➡️) e dadi logici con facce tipo “ripeti”, “salta”, “gira”.

Esercizio: Costruire sequenze di frecce che rappresentino movimenti precisi.

Esempio:

  • Crea una sequenza per “muoversi due passi avanti, girare a destra e camminare tre passi.”

Si possono anche fare gare a chi crea l’algoritmo più corto o quello più chiaro.

3. Costruzione di un algoritmo per piegare una maglietta in tre mosse

Prendi una maglietta distesa sul tavolo.

Obiettivo: Scrivere un algoritmo con tre istruzioni per piegarla.

Soluzione esempio:

  1. Piega la parte destra verso il centro.
  2. Piega la parte sinistra verso il centro.
  3. Piega la maglietta a metà dal basso verso l’alto.

I partecipanti possono provare a eseguire l’algoritmo e vedere se funziona davvero.

🧠 Test di autovalutazione

  1. Qual è la differenza tra algoritmo e istruzione singola?

  2. Come si può rappresentare una sequenza usando solo frecce?

  3. Perché il coding unplugged è utile anche nella scuola dell’infanzia?

  4. Costruisci un algoritmo in 4 passi per attraversare una griglia 4x4 evitando ostacoli, partendo dall’angolo in alto a sinistra.

✅ Soluzioni suggerite

  1. Un’istruzione singola è un solo comando (es. “vai avanti”), mentre un algoritmo è un insieme ordinato di istruzioni da eseguire in sequenza.

  2. Si può usare ogni freccia per rappresentare un passo o un movimento (➡️ = avanti, ⬅️ = indietro, ⬆️ = su, ⬇️ = giù). Sequenziando le frecce, si ottiene la rappresentazione di una sequenza.

  3. Perché permette ai bambini piccoli di sviluppare la logica, la capacità di prevedere risultati e lavorare su abilità come la lateralità, la memoria e la collaborazione, senza la necessità di saper usare il computer.

  4. Esempio di algoritmo: ⬇️ ⬇️ ➡️ ➡️ (due passi giù, due passi a destra). È importante che i passi evitino le caselle con ostacoli.

Ulteriori spunti per approfondire

  • Analisi degli errori: Cosa succede se un algoritmo è scritto male? Prova a modificare la sequenza e osserva come cambia il risultato. È un modo per capire l’importanza della precisione.

  • Ripetizioni e cicli: Introduci l’idea di “ripetere” azioni usando esercizi con tessere “ripeti” o con movimenti a tempo.

  • Condizioni: Simula con giochi “se allora” (es. “Se la strada è libera, vai avanti, altrimenti gira a destra”).


domenica 1 febbraio 2026

Corso Pensiero Computazionale e Coding per Tutti: 1 Cos'è il pensiero computazionale

Il pensiero computazionale:
una grammatica invisibile del mondo contemporaneo

Nel dibattito pubblico sull’intelligenza artificiale e sulla trasformazione digitale, si parla spesso di algoritmi, automazione e macchine “intelligenti”. Più raramente, però, ci si sofferma su ciò che rende possibile tutto questo: una particolare forma di razionalità, discreta ma pervasiva, che precede i computer e attraversa la vita quotidiana. È ciò che chiamiamo pensiero computazionale.

Contrariamente a quanto si potrebbe immaginare, non si tratta di una competenza riservata a programmatori, ingegneri o informatici. Il pensiero computazionale è, prima di tutto, un modo di affrontare i problemi: una capacità di scomporre la complessità, individuare strutture ricorrenti, isolare ciò che conta davvero e trasformarlo in una sequenza ordinata di azioni. In altre parole, è una forma di intelligenza pratica che utilizziamo continuamente, spesso senza esserne consapevoli.

Un concetto nato prima dei computer

Il termine nasce negli ambienti della ricerca educativa. Fu Seymour Papert, matematico e pedagogista, a intuire per primo che il contatto con il pensiero computazionale potesse trasformare il modo in cui i bambini apprendono e ragionano. Decenni dopo, Jeannette Wing ne ha sistematizzato il significato, proponendolo come una competenza chiave del XXI secolo: non una tecnica, ma una vera e propria alfabetizzazione cognitiva, paragonabile alla lettura o al calcolo.

La sua forza sta proprio qui: il pensiero computazionale non insegna cosa pensare, ma come pensare problemi complessi in modo efficace.

La logica delle azioni quotidiane

Organizzare una gita, pianificare una cena, gestire un progetto di lavoro: tutte queste attività implicano decisioni, priorità, vincoli di tempo e risorse. Chi le affronta in modo efficace, senza perdersi nei dettagli o farsi paralizzare dalla complessità, sta applicando — consapevolmente o meno — i principi del pensiero computazionale.

Il processo è sempre simile: si parte da un problema indistinto, lo si scompone in parti più piccole, si eliminano gli elementi superflui, si riconoscono situazioni già note e si costruisce una sequenza di azioni coerente. È una logica che ricorda quella dei computer, ma che in realtà precede la macchina ed è profondamente umana.

Le quattro operazioni fondamentali del ragionamento computazionale

Alla base di questo approccio si trovano quattro operazioni chiave.

La prima è la decomposizione: la capacità di frammentare un problema complesso in sottoproblemi più semplici e gestibili. È il passaggio che trasforma l’opacità in chiarezza.

Segue l’astrazione, ovvero l’arte di distinguere ciò che è essenziale da ciò che è irrilevante. Astrarre non significa semplificare superficialmente, ma isolare le variabili che contano davvero, riducendo il rumore cognitivo.

Il terzo elemento è il riconoscimento di schemi. Individuare somiglianze tra situazioni diverse permette di riutilizzare soluzioni già sperimentate, risparmiando tempo ed energia mentale. È uno dei meccanismi fondamentali dell’apprendimento umano.

Infine, vi sono gli algoritmi: sequenze ordinate di istruzioni che guidano l’azione passo dopo passo. Una ricetta di cucina, un piano di lavoro, una checklist: tutti esempi di algoritmi informali che strutturano il nostro agire quotidiano.

Pensiero computazionale e formazione del cittadino

Ridurre il pensiero computazionale a una competenza tecnica sarebbe un errore. In realtà, esso ha profonde implicazioni culturali e civiche. In un mondo governato da sistemi automatici, piattaforme digitali e decisioni algoritmiche, comprendere la logica dei processi diventa una forma di consapevolezza critica.

Chi possiede questa forma di pensiero è meno incline a subire la tecnologia come una scatola nera e più capace di interrogarsi sui suoi limiti, sulle sue regole implicite e sulle sue conseguenze sociali. In questo senso, il pensiero computazionale non è solo uno strumento operativo, ma anche un antidoto all’analfabetismo digitale.

Dalla scuola alla vita adulta

Non sorprende che oggi il pensiero computazionale sia al centro di molte riforme educative. Tuttavia, il suo valore non si esaurisce nei contesti scolastici. È una competenza trasversale, applicabile alle scienze come alle discipline umanistiche, alla gestione aziendale come alle scelte personali.

Imparare a pensare in modo computazionale significa allenare la mente alla chiarezza, alla progettualità e alla responsabilità delle decisioni. In un’epoca segnata dall’eccesso di informazioni e dalla complessità sistemica, questa forma di razionalità sobria e strutturata appare sempre meno opzionale e sempre più necessaria.

In definitiva, il pensiero computazionale non ci rende simili alle macchine. Al contrario, ci aiuta a essere più consapevolmente umani in un mondo di macchine.


🧠 1 Cos'è il Pensiero Computazionale

📘 Contenuti Didattici

Il pensiero computazionale non è un superpotere riservato ai programmatori: è una modalità di ragionamento che tutti, ogni giorno, applichiamo senza rendercene conto. È la capacità di affrontare un problema, grande o piccolo, in modo logico, strutturato e strategico, un po’ come farebbe un computer… ma con la nostra creatività umana.

Il termine fu coniato da Seymour Papert e successivamente ripreso da Jeannette Wing, che lo ha reso famoso nel mondo accademico come competenza fondamentale del XXI secolo.

Un esempio quotidiano

Immagina di dover organizzare una gita con gli amici. Devi decidere la destinazione, verificare chi viene, controllare i costi, prenotare i biglietti, e infine comunicare a tutti il programma. Anche senza saperlo, hai applicato pensiero computazionale: hai scomposto il problema, ignorato dettagli irrilevanti, trovato schemi comuni e creato un “algoritmo” di azioni.

Le quattro componenti fondamentali

  • 🔹 Decomposizione: Scomporre un problema in parti più piccole e gestibili. Esempio svolto: “Preparare una torta” diventa: comprare ingredienti → preparare impasto → infornare → decorare.
  • 🔹 Astrazione: Concentrarsi sugli elementi essenziali, ignorando ciò che non è rilevante. Esempio: Nel preparare la torta, non serve considerare il colore del grembiule, ma sì la temperatura del forno.
  • 🔹 Riconoscimento di schemi: Identificare modelli ricorrenti che possono semplificare il lavoro. Esempio: Notare che molte ricette prevedono “mescolare ingredienti secchi” e poi “aggiungere quelli liquidi”.
  • 🔹 Algoritmi: Creare una sequenza di istruzioni precise per risolvere un problema. Esempio: La ricetta scritta è un algoritmo: passo 1, passo 2, passo 3…

Questi strumenti non servono solo in informatica: sono utili in matematica, scienze, gestione aziendale, e perfino nelle decisioni personali.

🛠️ Attività ed Esercizi Svolti

Per imparare il pensiero computazionale bisogna “sporcarsi le mani” con esercizi concreti.

Esercizio 1 – Cena per 10 persone

Problema: Devi preparare una cena per 10 ospiti.

Soluzione con pensiero computazionale:

  1. Decomposizione: scegliere il menù, comprare ingredienti, cucinare, apparecchiare, servire.
  2. Astrazione: ignorare dettagli estetici non necessari (es. forma dei piatti) e concentrarsi su quantità e tempi.
  3. Riconoscimento di schemi: ricordare che ogni volta serve organizzare le cotture in modo da servire caldo.
  4. Algoritmo: redigere una tabella con orari di preparazione per ogni portata.

Esercizio 2 – Labirinto logico

Problema: Come uscire da un labirinto seguendo sempre la mano destra appoggiata al muro.

Risultato: Hai creato un algoritmo “meccanico” che funziona senza pensare, basato su una regola ricorrente.

📝 Test di Verifica

  1. Quale delle seguenti NON è una componente del pensiero computazionale?
    A. Decomposizione
    B. Intuizione
    C. Riconoscimento di schemi
    D. Algoritmi
    ✅ Soluzione

    B. Intuizione

  2. A cosa serve la decomposizione?
    A. Ignorare i dettagli
    B. Scomporre un problema complesso in parti più semplici
    C. Creare una lista di spesa
    D. Fare un disegno
    ✅ Soluzione

    B. Scomporre un problema complesso in parti più semplici

  3. Se segui una ricetta passo passo, stai usando:
    A. Un algoritmo
    B. Una mappa concettuale
    C. Una previsione
    D. Un ragionamento astratto
    ✅ Soluzione

    A. Un algoritmo

  4. Perché l’astrazione è utile?
    A. Per fare più calcoli
    B. Per evitare di concentrarsi su dettagli irrilevanti
    C. Per ricordare i passaggi
    D. Per aumentare la complessità
    ✅ Soluzione

    B. Per evitare di concentrarsi su dettagli irrilevanti

  5. Quale attività richiede maggiormente il riconoscimento di schemi?
    A. Risolvere un sudoku
    B. Fare la spesa
    C. Scrivere un tema
    D. Disegnare un ritratto
    ✅ Soluzione

    A. Risolvere un sudoku

📌 Suggerimenti per l’autovalutazione

Al termine della lezione, chiediti:

  • ✏️ Riesco a spiegare cos’è il pensiero computazionale a un amico senza usare parole difficili?
  • 🔍 Posso individuare le 4 componenti in una situazione reale della mia giornata?
  • 📋 Sono in grado di scrivere un algoritmo per risolvere un problema quotidiano?
  • 🎯 Posso applicare questo metodo in discipline diverse, come storia o scienze?

sabato 31 gennaio 2026

Corso sulla Struttura dell’Intelligenza Artificiale: 5 Creare una mini-AI autonoma


Creare una mini-AI autonoma

Obiettivo del modulo

Progettare, addestrare e deployare una micro-AI che svolge un compito ben definito (testo, immagini o decisioni), con pipeline completa: input → decisione AI → output → validazione, interfaccia d’uso (CLI, API o web), logging e salvataggio/ripristino dei pesi. Il percorso è hands-on e progressivo: si parte da un baseline semplice, poi si estende.

Scaletta passo-passo

🕐 Scoping e setup ambiente

  • Scegli il dominio:
    • Testo: classificatore di notizie (politica/sport/tech).
    • Immagini: generatore di descrizioni per immagini pre-caricate (feature estratte + template).
    • Decisioni: AI che suggerisce azioni su una checklist (regole+modello).
  • Definisci l’output: etichetta, punteggio, testo, raccomandazione con motivazione breve.
  • Setup: Python 3.10+, virtualenv, pacchetti minimi: pip install numpy pandas scikit-learn joblib fastapi uvicorn streamlit pydantic
  • Repo: struttura consigliata:
    mini_ai/
    ├─ data/ # dataset grezzi e processati
    ├─ models/ # pesi, vectorizer, versioni
    ├─ src/
    │ ├─ config.py
    │ ├─ preprocess.py
    │ ├─ model.py
    │ ├─ train.py
    │ ├─ eval.py
    │ ├─ serve_api.py # FastAPI
    │ └─ ui_streamlit.py # interfaccia web
    └─ logs/

🕑 Dati e metrica di successo

  • Raccolta: CSV con colonne minime (es. text,label per il testo; image_path,caption per immagini).
  • Split: train/val/test (70/15/15) con stratificazione per classi.
  • Metriche:
    • Classificazione: accuracy, F1 macro (classi sbilanciate), matrice di confusione.
    • Generazione (caption): BLEU/ROUGE (anche valutazione umana light: 1–5 coerenza).
    • Decisioni su checklist: precision@k e tasso di adozione (quante azioni proposte accettate).

🕒 Baseline funzionante (semplice & robusto)

Obiettivo: avere una prima versione end-to-end che produce un output coerente, anche se non perfetto.

  • Testo (consigliato per iniziare): CountVectorizer + Logistic Regression (veloce, solido, interpretabile).
    # src/train.py (estratto – baseline testo)
    import pandas as pd
    from sklearn.model_selection import train_test_split
    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.linear_model import LogisticRegression
    from sklearn.pipeline import Pipeline
    from sklearn.metrics import classification_report
    import joblib, os
    df = pd.read_csv("data/news.csv") # colonne: text,label
    train, test = train_test_split(df, test_size=0.2, stratify=df.label, random_state=42)
    pipe = Pipeline([
    ("vec", CountVectorizer(max_features=30000, ngram_range=(1,2))),
    ("clf", LogisticRegression(max_iter=200, n_jobs=-1))
    ])
    pipe.fit(train.text, train.label)
    pred = pipe.predict(test.text)
    print(classification_report(test.label, pred, digits=3))
    os.makedirs("models", exist_ok=True)
    joblib.dump(pipe, "models/news_baseline.joblib")
  • Immagini (baseline didattico): estrai feature con un backbone pre-addestrato (es. ResNet da torchvision), poi Nearest Neighbors per suggerire la caption dell’immagine più simile (semplice ma utile per il flusso end-to-end).
  • Decisioni: Rule-first + piccolo modello: regole deterministiche per i casi chiari; modello di classificazione binaria per consigliare “fai/non fare” dove le regole non bastano.

🕓 Validazione, error analysis, versioning

  • Valida sullo split di test; salva classification_report in logs/ con timestamp.
  • Errori ricorrenti: estrai i falsi positivi/negativi, crea una “lista nera” di pattern e una todo di miglioramenti (es. pulizia testo, stopword dominio-specifiche).
  • Versiona modelli/dati:
    # src/config.py
    MODEL_VERSION = "v1.0.0"
    ARTIFACT_DIR = f"models/{MODEL_VERSION}/"
    Salva anche le feature (vectorizer) e la configurazione usata (seed, parametri, vocabolario).

🕔 Interfacce d’uso (CLI, API, Web)

  • CLI (per uso locale/automazione):
    # src/model.py (inference)
    import joblib
    _pipe = joblib.load("models/news_baseline.joblib")
    def predict_text(txt: str):
    label = _pipe.predict([txt])[0]
    prob = max(_pipe.predict_proba([txt])[0])
    return {"label": label, "confidence": float(prob)}
    # cli.py
    import argparse
    from src.model import predict_text
    parser = argparse.ArgumentParser()
    parser.add_argument("--text", required=True)
    args = parser.parse_args()
    print(predict_text(args.text))
  • API (per integrazioni):
    # src/serve_api.py
    from fastapi import FastAPI
    from pydantic import BaseModel
    from src.model import predict_text
    app = FastAPI(title="Mini-AI API")
    class Item(BaseModel):
    text: str
    @app.post("/predict")
    def predict(item: Item):
    return predict_text(item.text)
    # Avvio: uvicorn src.serve_api:app --reload --port 8000
  • Web UI (demo rapida):
    # src/ui_streamlit.py
    import streamlit as st
    from src.model import predict_text
    st.title("🧠 Mini-AI Classificatore di Notizie")
    txt = st.text_area("Inserisci il testo della notizia")
    if st.button("Predici"):
    out = predict_text(txt)
    st.write(f"**Classe:** {out['label']} | **Confidenza:** {out['confidence']:.2f}")
    Avvio: streamlit run src/ui_streamlit.py

🕕 Logging, debugging, salvataggio/riuso pesi

  • Logging strutturato (JSON line per facile analisi):
    # src/logging_utils.py
    import json, time, os
    def log_event(event: dict, fname="logs/events.jsonl"):
    os.makedirs("logs", exist_ok=True)
    event["ts"] = time.time()
    with open(fname, "a", encoding="utf-8") as f:
    f.write(json.dumps(event, ensure_ascii=False) + "\n")
  • Usalo in API/UI:
    # dentro /predict
    res = predict_text(item.text)
    log_event({"route": "predict", "input_len": len(item.text), "output": res})
    return res
  • Salvataggio & ripristino: già visto con joblib; per reti neurali usa torch.save/model.save() (TF). Aggiungi checksum o hash del file e della config per riproducibilità.
  • Debugging:
    • stampa le top-n feature che “spingono” la predizione (es. coef_ di Logistic Regression) per audit.
    • logga eccezioni con exc_info=True, conserva input problematica in logs/bad_cases/.

🕖 Hardening & deploy

  • Seed & determinismo: imposta random_state ovunque per esperimenti ripetibili.
  • Config separata (.yaml o .json) per parametri (feature, modello, soglie).
  • Test: unit test su preprocess e su un paio di casi attesi del modello.
  • Docker (opzionale):
    # Dockerfile (minimal)
    FROM python:3.11-slim
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY . .
    CMD ["uvicorn", "src.serve_api:app", "--host", "0.0.0.0", "--port", "8000"]
  • Deploy: locale, VM, o PaaS (Railway/Render/Cloud Run). Esporre endpoint /predict; proteggi con chiave API se pubblico.

🔬 Lab guidato: micro-AI end-to-end

  1. Importa dati (CSV) e fai lo split con stratificazione.
  2. Addestra baseline (testo: CountVectorizer+LR) e salva pesi.
  3. Valida su test e salva report e matrice di confusione (immagine/CSV).
  4. Servi il modello via API FastAPI e prova con curl o Postman.
  5. Interfaccia Streamlit per demo; logga ogni richiesta.
  6. Itera: migliora preprocessing (stopword dominio-specifiche, n-grammi), confronta F1 e aggiorna versione (v1.1.0).

🧭 Design dell’autonomia: validazione & fallback

Evenienza reale: la mini-AI deve “sapere dire non so”. Aggiungi un validatore e un fallback:

  • Soglia di confidenza: se confidence < 0.55 → restituisci “richiedi conferma” o inoltra a regola/operatore.
  • Controlli di sicurezza: blocca input vuoti o troppo lunghi, rimuovi HTML/script.
  • Audit: salva i low-confidence per active learning e migliorare il dataset in seguito.

📈 Miglioramenti successivi (opzionali)

  • Text: TF-IDF, SVM, o DistilBERT (Hugging Face) con fine-tuning.
  • Immagini: CLIP per embedding e nearest neighbor con caption semantiche.
  • Decisioni: meta-policy: regole deterministiche + classificatore + spiegazioni (feature importanti) nel payload.

venerdì 30 gennaio 2026

Corso sulla Struttura dell’Intelligenza Artificiale: 4 Architetture complesse: dai layer alla logica modulare


Architetture complesse: dai layer alla logica modulare

Perché “architetture complesse”?

Quando i problemi crescono di difficoltà (linguaggio naturale, visione, serie temporali multivariate), non basta una rete “piatta”. Serve costruire modelli componibili, con blocchi riutilizzabili, che separano le responsabilità: estrazione di feature, memorie a lungo raggio, ragionamento sequenziale, generazione. Questo modulo insegna come passare dai singoli layer a moduli più ricchi – e come assemblarli in pipeline robuste.

1) Layer base: mattoni fondamentali

I layer sono le unità minime di calcolo. Conoscerne comportamenti e limiti è cruciale per non “abusare” della profondità o scegliere attivazioni/normalizzazioni inadatte.

  • Dense (fully connected): proiezioni lineari con attivazione non lineare (ReLU, GELU, SiLU). Ottimi come head finali o per integrare feature eterogenee.
  • Convolutional (Conv): estraggono pattern locali con condivisione dei pesi. Varianti utili: depthwise separable, dilated, residual. Nati per immagini, efficaci anche su sequenze 1D.
  • Ricorrenti (LSTM/GRU): gestiscono dipendenze temporali. Le LSTM eccellono su contesti lunghi; le GRU sono più leggere con prestazioni simili.
  • Transformer block: stack di Multi-Head Self-Attention (MHSA) + Feed-Forward Network (FFN), con residual + LayerNorm. Cattura dipendenze lunghe in parallelo.
<!-- Esempio di “blocco” astratto -->
Input → [Normalizzazione] → [Operazione principale] → [Dropout] → (+ Residual) → Output

Nota pratica: Normalizzazione prima del blocco (pre-norm) tende a stabilizzare il training di modelli molto profondi; il residuo riduce il rischio di vanishing gradient.

2) Dalla collezione di layer alla logica modulare

Un’architettura complessa non è solo “più layer”: è composizione. Si definiscono moduli con un’API chiara e testabile, che possono essere riutilizzati in punti diversi della rete.

  • Blocchi ripetibili: es. “ConvBlock(k, s)” con Conv → Norm → Attivazione → Dropout; “TransformerBlock(h, d)” con MHSA → FFN → Residual/Norm.
  • Percorsi paralleli (inception-like): più rami con kernel/attività diverse, poi concatenazione: migliore copertura di scale differenti.
  • Skip/Residual multi-scala: collegamenti tra livelli lontani per preservare dettagli (U-Net in segmentazione, encoder–decoder in NLP).
  • Conditioning: iniezione di segnali esterni (classe/tempo/contesto) nei blocchi tramite concatenazione, gating o attenzione condizionata.
<!-- Pseudocodice di un modulo riutilizzabile -->
def TransformerBlock(x):
x_norm = LayerNorm(x)
x_attn = MultiHeadAttention(x_norm, x_norm)
x = x + Dropout(x_attn) # residual
y_norm = LayerNorm(x)
y_ffn = FFN(y_norm)
y = x + Dropout(y_ffn) # residual
return y

3) Strutture moderne: encoder–decoder, attention, embedding

  • Embedding: mappa token/ID in vettori densi. Fondamentali in NLP; analoghi per categorie in tabellari. Si può includere positional encoding (sinusoidale o learnable) per preservare l’ordine.
  • Attention/MHSA: meccanismo che assegna pesi Query–Key–Value alle relazioni tra elementi. Multi-head = sotto-spazi diversi in parallelo.
  • Encoder–Decoder:
    • Encoder: comprime l’input in rappresentazioni contestualizzate (BERT-like).
    • Decoder: genera output condizionato all’encoder (traduzione, riassunto) o in modo autoregressivo (GPT-like).
    • Cross-attention: il decoder “guarda” l’encoder per ogni passo di generazione.

Scelte progettuali chiave

  • Maschere di attenzione: causale (no “sbirciare” il futuro) per generazione; bidirezionale per comprensione.
  • Label smoothing: regolarizza la classificazione su vocabolari grandi.
  • Ottimizzazione: AdamW + scheduler con warmup lineare spesso accelera la convergenza.

4) Dataset sequenziali e input testuali

Il successo di un’architettura complessa dipende dalla corretta preparazione del dato.

  • Tokenizzazione: BPE/WordPiece alleviano out-of-vocabulary e mantengono compattezza. Conservare special tokens (PAD, BOS, EOS, SEP).
  • Padding & masking: batch di lunghezze uniformi, con maschere per ignorare il padding nell’attenzione e nella loss.
  • Bilanciamento: shuffling, pesi di classe, sampling per evitare bias di frequenza.
  • Serie temporali: finestre scorrevoli, lookback/horizon, normalizzazione per feature (z-score/min-max), gestione di “missing” (imputazione, maschere).
  • Data leakage: attenti a non usare informazioni future in addestramento (split temporale rigoroso).

5) Pattern di addestramento stabili

  • Inizializzazione & attivazioni: He (ReLU/SiLU), Xavier (tanh); evitare saturazioni; LayerNorm/BatchNorm dove appropriato.
  • Regolarizzazione: dropout (attenzione e FFN), weight decay, early stopping, stochastic depth in reti profonde.
  • Gradiente: clip del gradiente su RNN/Transformer (specie con sequenze lunghe); mixed precision per velocità/memoria.
  • Curriculum & teacher forcing: per modelli autoregressivi; scheduled sampling per ridurre esposizione a distribuzioni diverse tra train/test.

6) Valutazione e metriche

  • Classificazione: accuracy, F1 (macro/micro), AUC; matrici di confusione per classi sbilanciate.
  • Generazione testo: perplexity, BLEU/ROUGE/METEOR; analisi qualitativa (allucinazioni, ripetizioni, coerenza).
  • Serie temporali: MAE/MSE/RMSE, MAPE; backtesting a più orizzonti (rolling window).

7) Laboratorio: Progettare un piccolo encoder–decoder per generazione frasi

Obiettivo: costruire un modello che generi frasi di risposta data un’istruzione breve (mini traduzione o dialogo toy).

Dataset suggeriti

  • Tatoeba o coppie frase–frase semplificate (es. “it → en” ridotto) oppure un dataset custom di prompt–risposta (1000–5000 esempi bastano per il prototipo).

Passi operativi

  1. Preprocessing: tokenizzazione subword (BPE/WordPiece), definizione vocabolario, aggiunta di BOS/EOS, padding/truncation; split train/val/test.
  2. Embedding & Positional Encoding: dimensione embed 128–256; posizionale sinusoidale o learnable.
  3. Encoder: 2–4 TransformerBlock con 4–8 teste, FFN 2–4× dimensione embed, dropout 0.1–0.2.
  4. Decoder: 2–4 blocchi con masked self-attention + cross-attention verso l’encoder; tie embeddings opzionale.
  5. Loss & training: cross-entropy con label smoothing 0.1; AdamW (lr 3e−4) + warmup; early stopping via perdita di validazione.
  6. Decoding: greedy per debug; poi beam search (k=3–5) o top-k/top-p per qualità/varietà.
  7. Valutazione: BLEU/ROUGE su test; rassegna qualitativa di buone/cattive generazioni per guidare i miglioramenti.
<!-- Pseudocodice di montaggio (stile Keras/PyTorch-agnostico) -->
src = Input(shape=(T_src,))
tgt = Input(shape=(T_tgt,))
src_emb = TokenEmbedding(V, d)(src) + PositionalEncoding(T_src, d)
tgt_emb = TokenEmbedding(V, d)(tgt) + PositionalEncoding(T_tgt, d)
enc = src_emb
for _ in range(N_enc):
enc = TransformerBlock(d, heads=H, ffn=4*d, dropout=0.1)(enc)
dec = tgt_emb
for _ in range(N_dec):
dec = MaskedSelfAttentionBlock(d, heads=H, dropout=0.1)(dec)
dec = CrossAttentionBlock(d, heads=H, context=enc, dropout=0.1)(dec)
dec = FeedForwardBlock(d, ffn=4*d, dropout=0.1)(dec)
logits = Dense(V)(dec) # head linguistica
model = Model([src, tgt], logits)

Estensioni opzionali: weight tying embedding/output, shared encoder per multi-task, riduzione complessità con local attention per sequenze lunghe.

8) Errori comuni & best practice

  • Maschere mancanti: senza causal mask il decoder “vede il futuro” e impara scorciatoie.
  • Padding non mascherato: il modello impara a “predire” zeri: sempre applicare la mask del padding in attenzione e loss.
  • Learning rate inadeguato: troppo alto → divergenza; usare warmup e scheduler.
  • Overfitting precoce: aumentare dropout/weight decay, usare early stopping, più dati/augment.
  • Leakage temporale: nei dati sequenziali rispettare la cronologia nei split e nelle finestre.

9) Checklist rapida di design

  • Definisci chiaramente input/output e loro natura (immagini, testo, serie).
  • Scegli i moduli (Conv/RNN/Transformer) in base a località vs lunga dipendenza.
  • Applica normalizzazione, residual, dropout in ogni blocco profondo.
  • Stabilisci metriche coerenti con il task (F1/BLEU/MAE) e un protocollo di validazione.
  • Automatizza il training (checkpoint, early stopping, logging) e prova più semi.

giovedì 29 gennaio 2026

Corso sulla Struttura dell’Intelligenza Artificiale: 3 Progettare e addestrare un mini-modello


Progettare e addestrare un mini-modello

🎯 Obiettivo del modulo

Comprendere e sperimentare tutte le fasi necessarie per costruire e addestrare un modello di intelligenza artificiale semplice ma completo, utilizzando una rete neurale di tipo MLP (Multi-Layer Perceptron). Il modulo guida passo dopo passo nella realizzazione di un mini-engine per il training, includendo anche tecniche di miglioramento delle prestazioni come la normalizzazione, il dropout e l’early stopping. L’attività pratica culmina nell’allenamento di una mini-AI su dataset personalizzati.

📌 Contenuti dettagliati

🔧 Architettura MLP (Multi-Layer Perceptron)
  • Cos’è un MLP e perché è utile per problemi di classificazione e regressione.
  • Struttura base: input layer, hidden layer(s), output layer.
  • Attivazioni (ReLU, sigmoid, softmax) e funzione di output in base al compito.
  • Numero di neuroni e strati: come sceglierli e con quali criteri.
⚙️ Costruzione dell’engine di training
  • Forward pass: calcolo dell’output predetto dato l’input.
  • Loss function: scelta della funzione di perdita (MSE, cross-entropy) in base al tipo di compito.
  • Backward pass: calcolo dei gradienti tramite retropropagazione.
  • Ottimizzazione: aggiornamento dei pesi con gradient descent, SGD o Adam.
🧪 Tecniche per migliorare l’addestramento
  • Normalizzazione: scaling degli input (es. MinMax, Z-score) per velocizzare la convergenza.
  • Dropout: disattivazione casuale di neuroni durante il training per evitare overfitting.
  • Early stopping: interruzione automatica dell’addestramento quando non migliora più la validazione.
📊 Metriche e validazione
  • Accuracy, precision, recall, F1-score: come misurarle e quando usarle.
  • Divisione in training/validation/test set.
  • Visualizzazione delle curve di loss e accuratezza.

🧪 Laboratorio pratico – Allenare una mini-AI

Obiettivo: Costruire e addestrare una rete neurale MLP da zero (senza usare librerie avanzate come TensorFlow o PyTorch) su un dataset a scelta.

Dataset consigliati:

  • Classificazione emoji: data una parola o frase, predire l'emoji più coerente.
  • MNIST-like (cifre disegnate): classificazione di immagini semplici.
  • Sentiment Analysis: valutare se un testo è positivo o negativo.

Fasi del laboratorio:

  1. Definizione del dataset personalizzato.
  2. Preprocessing dei dati e normalizzazione.
  3. Costruzione della rete MLP in Python o pseudocodice.
  4. Definizione delle funzioni di forward, loss e backward.
  5. Implementazione dell’ottimizzazione (SGD o Adam).
  6. Aggiunta di dropout e early stopping.
  7. Addestramento e monitoraggio della rete.
  8. Valutazione delle prestazioni e visualizzazione dei risultati.

🧠 Competenze acquisite

  • Progettare una rete neurale MLP funzionale da zero.
  • Comprendere a fondo il processo di addestramento e ottimizzazione.
  • Saper applicare tecniche di regolarizzazione e metriche di validazione.
  • Allenare un modello su dati reali e interpretarne le performance.

mercoledì 28 gennaio 2026

Corso sulla Struttura dell’Intelligenza Artificiale: 2 Mattoni matematici e computazionali


Mattoni matematici e computazionali

Destinatari: studenti universitari, autodidatti in AI, data scientist junior, insegnanti STEM
Prerequisiti: conoscenze base di algebra lineare, derivate, Python


🎯 Obiettivi del modulo

  • Comprendere le basi matematiche e computazionali che sottendono il funzionamento di una rete neurale.
  • Familiarizzare con vettori, matrici e tensori come strutture fondamentali nella rappresentazione dei dati e dei modelli.
  • Introdurre i concetti di calcolo differenziale automatico (autodiff) e computational graph.
  • Acquisire i primi strumenti pratici per lavorare con librerie come NumPy e PyTorch.
  • Costruire da zero una rete neurale semplice con forward pass e backpropagation.

🧱 Contenuti


1. 📐 Vettori, matrici e tensori: come ragiona il modello

  • Le reti neurali trattano input numerici come vettori (1D), matrici (2D) o tensori (nD).
  • Ogni livello di una rete effettua operazioni matriciali: moltiplicazioni, somme, funzioni di attivazione.
  • Il tensore è l’unità fondamentale: ad esempio, un batch di immagini RGB è un tensore 4D (batch, altezza, larghezza, canali).

📌 Esempio pratico:

  • Un input , un layer , output

✅ Competenze attese: interpretare il significato geometrico e computazionale di una rete come sequenza di trasformazioni lineari + non linearità.


2. 🔁 Differenziazione automatica e backpropagation

  • La funzione obiettivo (loss function) misura quanto il modello sbaglia: ad esempio MSE, cross-entropy.
  • Il calcolo del gradiente serve a capire come modificare i pesi per ridurre la loss.
  • Backpropagation sfrutta la regola della catena per aggiornare ogni peso in funzione del gradiente della loss rispetto a quel peso.

🔬 Differenziazione automatica:

  • Metodo che permette di calcolare derivate esatte senza scriverle manualmente.
  • Le librerie moderne (es. PyTorch) costruiscono un computational graph e poi lo attraversano all’indietro per calcolare i gradienti (reverse-mode autodiff).

📌 Concetto chiave: l’ottimizzazione nei modelli neurali è possibile solo grazie alla propagazione del gradiente lungo il grafo computazionale.


3. 🧠 Struttura dei dati nei modelli neurali

  • I dati (immagini, testo, suono) devono essere numerizzati e organizzati in tensori.
  • Input → hidden layers → output: ogni livello produce una trasformazione.
  • I pesi sono rappresentati come matrici/tensori e memorizzati come parametri addestrabili.
  • Le architetture più complesse (CNN, RNN, Transformer) si costruiscono su questi elementi base.

📌 Focus: ciò che cambia è l’organizzazione e la connettività, ma le operazioni sono sempre su tensori.


4. ⚙️ Introduzione a NumPy e PyTorch

✅ NumPy:

  • Libreria fondamentale per calcolo scientifico in Python.
  • Operazioni su array, broadcasting, algebra lineare.

✅ PyTorch:

  • Costruito su tensori simili a NumPy ma con autodiff e GPU support.
  • Ogni Tensor tiene traccia della sua storia computazionale se requires_grad=True.
  • torch.autograd permette di eseguire backprop automaticamente.

📌 Esempio:

import torch

x = torch.tensor([1.0, 2.0], requires_grad=True)
y = x ** 2 + 3 * x
z = y.sum()
z.backward()

print(x.grad)  # output: gradiente di z rispetto a x

🧠 Computational Graph

  • Ogni operazione crea un nodo nel grafo.
  • PyTorch costruisce il grafo in tempo reale ("define-by-run").

🧪 LAB: Implementare una rete neurale semplice da zero

Obiettivo: costruire un modello con:

  • 1 layer input
  • 1 layer hidden (ReLU)
  • 1 output (softmax o lineare)

Attività step-by-step:

  1. Inizializzazione pesi e bias con NumPy
  2. Forward pass: calcolo output
  3. Loss function: MSE o Cross-Entropy
  4. Backpropagation manuale: calcolo derivata, aggiornamento parametri
  5. Addestramento su un dataset semplice (es. XOR, AND, o dataset sintetico)
  6. Plot della loss nel tempo

📌 Sfida bonus: reimplementare la stessa rete usando PyTorch e confrontare risultati, performance e semplicità del codice.


📎 Materiali forniti

  • Slide PDF con tutti i concetti e formule
  • Foglio guida per il LAB (istruzioni + codice base)
  • Notebook Colab con versione PyTorch + visualizzazione computational graph
  • Dataset di test (XOR, MNIST semplificato)

🧩 Conclusione

I tensori sono i mattoni del ragionamento computazionale, le derivate sono la spinta dell’apprendimento, e librerie come PyTorch sono i mezzi con cui possiamo esplorare e costruire reti neurali. In questo modulo lo studente passa da concetti astratti a realizzazione pratica, unendo teoria matematica, logica computazionale e coding efficace.


🧾 Vuoi che converta il modulo in:

  • Codice HTML per Blogger
  • Scheda didattica PDF/Word
  • Notebook Jupyter (Colab ready)

Fammi sapere, posso fornirti tutto il materiale pronto all’uso.

Corso Pensiero Computazionale e Coding per Tutti: 3 Il linguaggio binario e i sistemi di numerazione

3 Il linguaggio binario e i sistemi di numerazione Introduzione: perché il binario? Immagina un corridoio pieno di lampadine. Ogni lampadi...