(F#) Project Euler .net – Problema n. 1

Molto spesso, per imparare un nuovo linguaggio di programmazione, si esaminano alcuni problemi matematici. Questo avviene per due motivi: il primo è motivo deriva dal fatto che molti piccoli problemi matematici sono molto semplici e quindi non aggiungono livelli di complessità all’attuale nostro problema di imparare un particolare linguaggio di programmazione. Il secondo motivo è dato dal fatto che questo approccio consente di imparare in modo più efficace i costrutti di base della programmazione nel linguaggio scelto: cicli, istruzioni condizionali, assegnazione di valori, visualizzazione del risultato e così via.

Un sito interessante che raccoglie molti di questi problemi matematici, in ordine di difficoltà crescente, è “Project Euler .net” (http://projecteuler.net). Potete registrarvi al sito per provare a dare le vostre soluzioni. Quando fornirete una soluzione corretta, vedrete nel vostro “pannello” dei problemi le soluzioni trovate e potrete anche visualizzare un file PDF contenente una spiegazione dettagliata della soluzione proposta.

Utilizzerò pertanto qualcuno di questi problemi per costruire il nostro “vocabolario” delle istruzioni di F#. Il fatto che il sito abbia il suffisso “.net” è solamente un caso: non ha alcuna attinenza con il Framework .NET  ;-)

Il primo problema consiste nell’esaminare e sommare tra loro tutti i multipli di 3 e di 5 in un intervallo di numeri naturali che va da 1 a “x”. Per esempio, tra 1 e 9, la somma dei multipli di 3 e 5 è pari a 23 (= 3+5+6+9).

Trovare la somma di tutti i numeri multipli di 3 e di 5, tra 1 e 999.

Possiamo risolvere questo problema in almeno due modi (ma probabilmente anche in molti altri). In entrambi i casi otteniamo il numero 233168.

La prima soluzione è la seguente:

#light

let rec sum_mul xs =
  match xs with
  | []    -> 0
  | y::ys when y % 3 = 0 || y % 5 = 0 -> y + sum_mul ys
  | y::ys -> sum_mul ys

let sum = sum_mul [1 .. 999]

printfn "%d" sum

Esaminiamo come funziona questa prima soluzione.

La direttiva #light permette di scrivere il codice in modo più semplice, senza le parole chiave begin … end e senza altri caratteri che indicano il termine delle righe di istruzione (come il “;” di C#, per esempio). I cicli o i blocchi di codice sono definiti dall’indentazione del codice (cioè dai rientri), mentre il termine delle istruzioni è semplicemente riconosciuto dalla presenza di spazi e di ritorni a capo.

Nella seconda riga abbiamo inserito una funzione ricorsiva, denominata sum_mul, che accetta il parametro xs.

Nelle righe dalla 3^ alla 6^ c’è un esempio di pattern matching: un metodo elegante per gestire varie alternative (come uno switch o un select case). Il programma confronta xs con alcuni pattern, ciascuno scritto in una riga separata e preceduti dal simbolo “|” (pipe). Nel primo caso il confronto ha successo quando xs è una lista vuota e in tal caso sum_mul restituisce 0 (zero).

Negli altri casi, xs corrisponde a una lista, in cui il primo elemento (la testa della lista) viene chiamato y e il resto della lista (la coda della lista) viene chiamato ys.

Se y è divisibile per 3 o per 5 (utilizzando l’operatore modulo: %) aggiungiamo il numero al risultato e poi eseguiamo la stessa funzione ricorsivamente per la coda della lista. In caso contrario, semplicemente saltiamo il valore di testa e continuiamo ad esaminare la coda della lista.

Nell’8^ riga chiamiamo effettivamente la funzione sum_mul passando una lista come argomento. Questa lista è composta da tutti i numeri interi da 1 a 999 (o qualsiasi altro numero abbiate fissato come numero finale).

Per eseguire il programma e visualizzare il risultato potete premere F5 come al solito (l’istruzione printfn stamperà il risultato in una finestra analoga al prompt di comandi), oppure potete evidenziare la porzione di codice da eseguire e premere contemporaneamente ALT + INVIO. In quest’ultimo caso, il programma sarà eseguito e il risultato sarà visibile nella finestra “F# interactive” che comparirà nella parte inferiore del video.

La seconda soluzione invece è maggiormente ottimizzata:

#light

let sum_mult max step =
  let n = max / step
  step*n*(n + 1)/2

let max = 999
let sum2 = sum_mult max 3 + sum_mult max 5 - sum_mult max 15

printfn "%d" sum2

Partendo dal presupposto che stiamo sommando tutti i multipli di 3 e di 5, possiamo anche effettuare una semplice operazione per trovare tutti i multipli dell’uno e dell’altro valore, invece di provare tutti i valori nell’intervallo considerato (da 1 a 999). In tal caso dobbiamo anche sottrarre tutti i multipli di 15, perché 15 è divisibile sia per 3 sia per 5, e quindi dobbiamo evitare di contare tali valori per due volte.

Ricordando che la somma dei primi n numeri interi è uguale a n*(n+1)/2, possiamo utilizzare questa semplice formula per eseguire l’operazione desiderata, prima con il numero 3, poi con il numero 5 e infine con il numero 15.

Nella 2^ linea definiamo la funzione sum_mult che prende due argomenti interi: max e step.

Nella linea successiva, definiamo un identificatore locale denominato n, il cui ambito di visibilità è limitato all’interno della funzione sum_mult.

Il resto del codice è estremamente semplice, dato che applichiamo la formula sopra indicata.

Confrontando la complessità computazionale dei due programmi (chiamata “O grande”), troviamo che nel primo caso abbiamo una complessità O(n), mentre nel secondo caso abbiamo O(1). Nel secondo caso, quindi, la complessità (e la durata di esecuzione) è indipendente dal numero di valori da esaminare (in questo caso 999).

 

N.B. lo spunto per questo post e l’informazione sul sito Project Euler .net è stato gentilmente concesso da Claudio Cherubino (http://www.fsharp.it e http://www.claudiocherubino.it/). Grazie!

Evento tecnico a Belluno (“Community Tour”)

Questo post per informarvi che sto organizzando un evento tecnico: il “Community Tour” a Belluno, con la collaborazione di Microsoft Italia, delle Community tecniche XeDotNet e DotNetWork e dell’Ordine degli Ingegneri della Provincia di Belluno.

Dopo varie consultazioni, preventivi ecc. ecc., abbiamo definito la data di Venerdì 15 Ottobre 2010, soltanto al pomeriggio, presso la sala riunioni dell’Ordine degli Ingegneri della Provincia di Belluno, in centro a Belluno (Piazza Martiri n. 2, a fianco del Teatro Comunale, 4° piano). Mappa: http://www.ordineingegneri.bl.it/main/sede.aspx.

La sala ha una capienza di 40-45 persone e l’Ordine la mette a disposizione gratuitamente.

Ci saranno 3-4 sessioni di un’ora nel pomeriggio dalle 14 alle 18.30, incentrate su Visual Studio 2010, Windows Azure e forse su Windows Phone 7.

Appena possibile sarà aperta una pagina per le iscrizioni sul sito degli eventi di Microsoft Italia.

F# – Il blog di Don Syme su F#

Un blog interessante sulla programmazione in F# di Don Syme: http://blogs.msdn.com/b/dsyme/.
Vi sorprenderà scoprire che i post iniziano a Gennaio 2005, sul linguaggio F# definito un linguaggio di ricerca (nato nei laboratori di Microsoft Research). Questo “nuovo linguaggio”, alla fine non è poi nemmeno così tanto nuovo, visto che ha già ben 5 anni di “vita”.
Sicuramente, però, è un linguaggio nuovo per quasi tutti gli sviluppatori e per le aziende.
Sono pronto a scommettere che questo linguaggio avrà un grande futuro…

F#: un linguaggio multi-paradigma

F# utilizza tre paradigmi di programmazione: oltre alla programmazione funzionale, già citata, adotta anche il paradigma della programmazione imperativa e quello della programmazione orientata agli oggetti, permettendo di utilizzarli tutti insieme in modo coerente e ben orchestrato.

Questo approccio multi-paradigma può quindi essere utilizzato con le librerie .NET per eseguire attività di quali l’implementazione di interfacce grafiche (GUI), l’accesso ai dati, la programmazione distribuita e molto altro.

La programmazione funzionale, adottata dal nuovo linguaggio F#, è forse quella che meno è conosciuta da molti programmatori e questo richiede del tempo per impararla e per padroneggiarla, ma rende la programmazione più semplice, per vari motivi: i programmi F# tendono ad essere scritti in modo più formalmente corretto e l’inferenza dei tipi rende i programmi più corti e chiari.

Sebbene sia un linguaggio di derivazione FORTRAN e quindi orientato anche al calcolo scientifico, non è un linguaggio confinato solo nell’ambito scientifico e accademico: può essere utilmente impiegato per migliorare gli algoritmi utilizzati nelle nostre applicazioni e quindi migliorare le prestazioni di queste ultime.

Con F# la programmazione funzionale diventa realmente pratica, facile da imparare e una potente estensione della piattaforma .NET.

printfn “Hello World!”

Ebbene sì, il titolo di questo post è esattamente l’istruzione che in F# permette di stampare la stringa “Hello World!“, come previsto dal copione di qualsiasi presentazione di un linguaggio di programmazione.

In questo blog raccoglierò informazioni su F#, il linguaggio “managed” sulla piattaforma .NET di Microsoft, un linguaggio funzionale che esce un po’ dagli schemi classici della programmazione in Visual Basic e in C#.

A presto!