Giochiamo con MATLAB alla scoperta dei numeri.

Numeri

Benvenuti al nostro terzo appuntamento dedicato a MATLAB ed al suo utilizzo. Per questa "occasione" pensavamo di proporvi un gioco divertente che sia una fusione tra matematica, programmazione e divertimento. Dato che stiamo prendendo confidenza con questo software, perchè non provare ad usarlo per far della matematica? Oggi vi presentiamo un esperimento da fare in un momento di pausa per divertirvi programmando e approfittare per prendere confidenza con questo straordinario strumento. Siete pronti?

L'idea mi è venuta per caso, guardando il conta chilometri della macchina durante un viaggio. Benchè io non sia affatto un matematico, sono sempre stato molto affascinato dai numeri e dalle simmetrie. E con quueste premesse i numeri palindromi non potevano non suscitare il mio interesse. Ed ecco che, per assecondarlo, ho pensato di sperimentare con MATLAB la creazione di un codice che faccia proprio questo: scovare i numeri palindromi.
Palindromo è una parola che viene dal greco antico πάλιν "di nuovo" e δρóμος "percorso", che vuol dire "che può essere percorso in entrambi i versi".
Non so a voi ma a me la cosa suscita un fascino irresistibile.
Bene, ecco, ho pensato allora di chiedermi: quanti numeri palindromi sono già stati indicati dal mio conta chilometri? E quanti ce ne saranno entro i prossimi 40000?
Ovviamente da qui le domande seguono a ruota quindi direi di passare subito al codice.
Premetto che l'applicazione è del tuttto funzionante ma ho ancora alcune idee per migliorarla per cui diciamo che quella che vi propongo è una versione release client 0.3.

Le prime istruzioni utilizzate sono state già analizzate in una delle puntate precedenti e pertanto non le commento.

clear all
close all
clc

La prima vera riga di codice è di solo benvenuto e di spiegazione di che cosa farà il programma

disp('Questo programma calcola tutti i numeri palindromi in un intervallo.');

Questo codice lavora sulla base dell'inserimento di due valori come estremi inferiore e superiore dell'intervallo all'interno del quale cercare. Purtroppo i numeri sono infiniti, pertanto questo si rende indispensabile.

% Inserimento degli estremi
m=input('\nInserisci l''estremo inferiore di ricerca -> ');
n=input('Inserisci l''estremo superiore di ricerca -> ');

Sempre nella prima parte del codice dichiariamo una variabile di appoggio che sarà più chiaro avanti a cosa servirà

% Creo un indice di appoggio
index=1;

Bene. Adesso iniziamo a fare sul serio: tutto il codice è, in realtà, un lunghissimo ciclo for in maniera tale da realizzare l'analisi di ciascun numero in maniera più comoda. Effettuiamo, quindi, il controllo dei numeri.

% Controllo dei numeri
for i=m:1:n
% Conversione del numero in vettore
a=num2str(i);
% Calcolo la lunghezza del vettore
b=length(a);
% Utilizzo una variabile di appoggio per la lunghezza
count=0;

Qui abbiamo, prima di tutto, utilizzato un'istruzione per convertire il numero, una variabile reale, in un vettore.
Questo si rende indispensabile perché dovremmo essere in grado di effettuare il puntamento selettivo a ciascuna cifra che compone il numero complessivo indipendentemente dalla sua lunghezza e ciò non sarebbe possibile se avessi a che fare con un numero.

if mod(b,2)==0
for j=1:1:b/2
% Scansione vera e propria
if a(j)==a(b+1-j)
% Controllo il numero a coppie di valori procedendo
% dall'esterno verso l'interno.
count=count+1; % incremento la variabile di appoggio
else
break;
end
end

Ho inserito diversi commenti all'interno del codice in modo tale da rendere tutto più immediatamente fruibile. Tuttavia, vale la pena di specificare che questo pezzo del codice effettua la divisione per due per verificare se il numero è pari o dispari. In questa prima parte, in particolare, analizziamo i numeri pari. Se il numero è pari, per verificare che sia palindromo dovrò necessariamente fissare un asse di riferimento di osservazione che sarà sempre al centro del numero, ovvero metà della sua lunghezza. Se il numero è lungo un numero pari di cifre, allora l'asse di simmetria sarà tra due cifre mentre se il numero è dispari l'asse di simmetria si troverà sulla cifra centrale.
Una volta capito che il numero è (di lunghezza) pari, passo ad effettuare il controllo in un ciclo che utilizza un indice che varia dalla posizione uno alla posizione b/2, ovvero metà. Questo codice ottimizza anche il numero di operazioni perché effettua soltanto b/2 controlli invece che b (come nella prima versione che avevo realizzato). I secondi b/2 controlli, infatti, non sono necessari, per ovvi motivi.
Per ciascuno dei controlli che vengono effettuati, incremento la variabile di appoggio che avevo creato prima e vado avanti.

A questo punto la variabile di appoggio viene effettivamente utilizzata: se il suo valore risulterà pari al numero di coppie di numeri esaminate, vorrà dire che tutti i controlli avranno dato esito positivo, ergo il numero è palindromo. Ho previsto, in questa versione del codice, la scrittura del numero effettivamente trovato all'interno di un vettore che chiamo pal e deve necessariamente essere allocato dinamicamente perché quando comincio non sono in grado di dire quanti numeri palindromi verranno trovati da questo codice.

if count==b/2
pal(1,index)=i;
index=index+1;
end

Se quella condizione di if non dovesse essere verificata, vorrà dire che la lunghezza del numero sarà risultata essere dispari. Per le considerazioni che sono state fatte in precedenza, il controllo su questi numeri sarà fatto come segue

elseif mod(b,2)==1
for j=1:1:(b/2+.5)
% Scansione vera e propria
if a(j)==a(b+1-j)

anche in questo caso incrementerò la variabile di appoggio ed effettuerò la scrittura del numero, se effettivamente palindromo, all'interno del vettore di cui abbiamo parlato prima.
Ovviamente sto riportando soltanto alcuni pezzi di codice utile ma va da sé che i cicli così riportati risultano incompleti perché si vede chiaramente che alcune delle istruzioni non si chiudono con un "end".
A questo punto, vediamo quanti ne ho trovati.

len=0;
for j=1:1:length(pal)
if pal(1,j)~= 0
len=len+1;
end
end

E mostriamo questo risultato tramite una semplice espressione

s=horzcat('I numeri palindromi trovati sono ', num2str(len), ' su ', ...
... num2str(n-m), ' controllati.');
disp(s);
disp(pal);

Carino, vero? Si tratta di un programma che conta pochissime righe di codice che però è in grado di svolgere il compito in maniera egregia. Nell'attesa di decidere che ho realizzato la versione definitiva, sto cercando di farmi venire in mente tutte le idee che posso per potenziare il codice e magari potrei utilizzare i commenti per raggiungere i pezzi di codice. Ovviamente stiamo parlando di piccoli aggiusti e ritocchi perché, come dicevo in apertura, il programma è funzionalmente completo.

Prima di lasciarvi, però, credo sarebbe interessante per voi, e certamente divertente per me, farvi vedere un altro programma che ho sviluppato allo scopo di trovare… Beh, facciamo così, questa volta me lo dite voi.

Per rendere questa sfida ancora più interessante, ho eliminato tutti i commenti dal codice lasciando semplicemente le istruzioni utili ad eseguire le singole operazioni.
Vi preannuncio che non è difficile ma con poche variazioni rispetto al codice che abbiamo appena visto è possibile realizzare un programma completamente diverso.

m=input('\nInserisci l''estremo inferiore di ricerca -> ');
n=input('Inserisci l''estremo superiore di ricerca -> ');
k=0;
for i=m:1:n
div(1,i)=i;
appo=0;
for j=length(div):-1:1
if mod(i, j)==0
appo=appo+1;
end
end
if appo==2;
prime(1,k)=i;
k=k+1;
s=num2str(i);
disp(s);
end
end

Allora? Secondo voi che cosa fa questo programma? E una volta che avete capito questo, suggeritemi: cosa posso fare per renderlo migliore, più completo? E ancora, voi come lo avreste sviluppato? Avete pensato ad un algoritmo migliore?

Ora che avete letto queste righe probabilmente vi sarà più chiaro un concetto: con MATLAB non esiste limite a quello che potete fare!

NB: come per qualunque programma, anche i codici che io ho scritto non sono necessariamente i migliori o i più validi oppure il più efficienti per implementare un algoritmo… Diciamo, però, che questa è la soluzione migliore che mi venute in mente. Ecco perché la domanda "Voi come lo avreste fatto?", in realtà, è la più importante!

 

Quello che hai appena letto è un Articolo Premium reso disponibile affinché potessi valutare la qualità dei nostri contenuti!

 

Gli Articoli Tecnici Premium sono infatti riservati agli abbonati e vengono raccolti mensilmente nella nostra rivista digitale EOS-Book in PDF, ePub e mobi.
volantino eos-book1
Vorresti accedere a tutti gli altri Articoli Premium e fare il download degli EOS-Book? Allora valuta la possibilità di sottoscrivere un abbonamento a partire da € 2,95!
Scopri di più

5 Comments

  1. Antonello Antonello 11 luglio 2013
  2. Giorgio B. Giorgio B. 11 luglio 2013
  3. Piero Boccadoro Piero Boccadoro 11 luglio 2013
  4. Piero Boccadoro Piero Boccadoro 11 luglio 2013
  5. tre_spade@hotmail.com 16 luglio 2013

Leave a Reply

Raspberry Pi 3 GRATIS! (Win10 compatibile)

Fai un abbonamento Platinum (EOS-Book + Firmware), ricevi in OMAGGIO la RASPBERRY 3, inviaci il tuo progetto e OTTIENI IL RIMBORSO