San Valentino in Haskell
by Juna

Una storia d'amore e di numeri

L’amore ha finito per ispirare poeti e letterati di ogni epoca e perché no…probabilmente anche i matematici.

In effetti già Pitagora di Samo aveva fatto distinzione, ponendo i numeri in apposite categorie, tra numeri “maschili” e numeri “femminili”: a quanto pare (poiché non lasciò nulla di scritto) egli reputava maschili i numeri dispari e femminili i numeri pari. Non basta: con un piglio che potrebbe essere definito quasi misogino, associò ai numeri femminili e pari un’ idea di infinitezza e quindi di imperfezione e a quelli maschili (nemmeno a dirlo ;)) di limitatezza e quindi di perfezione.

C’è una forma di “attrazione” reciproca che riguarda i numeri ed è quella che permette di definire i numeri fidanzati:

I numeri fidanzati sono quei numeri tali che la somma dei divisori del primo (escluso l’1 ed il numero stesso) da come risultato il secondo e viceversa.

Haskell è un linguaggio funzionale particolarmente elegante; per determinare se due numeri sono fidanzati definiamo innanzitutto una funzione che dato un intero n restituisce somma dei suoi divisori, avendo cura di escludere già dalla lista il numero 1 ed il numero stesso.

A prescindere dalla definizione di tipo della funzione,

sumdiv :: Int → Int

si possono fare due scelte per ottenere questo valore; la prima è quella che utilizza un singolo generatore in cui viene esplicitamente indicata l’esclusione di 1 ed n:

sumdiv n = sum [x | x <- [1..n], n `mod` x == 0, x /= 1, x /= n]

La seconda è quella che definisce una versione personalizzata delle funzioni init e tail, che potrebbero restituire un errore a causa di una lista vuota, e l’operatore di composizione per escludere il primo e l’ultimo elemento dalla somma dei divisori:

init’ :: [a] → [a]
init’ [] = []
init’ xs = init xs

tail’ :: [a] → [a]
tail’ [] = []
tail’ xs = tail xs

sumdiv :: Int → Int
sumdiv n = (sum . init’ . tail’) [x | x <- [1..n], n `mod` x == 0]

Definita questa funzione, il “test di fidanzamento” di due numeri n ed m si può implementare con una funzione a due parametri:

fidanzati:: Int → Int → Bool
fidanzati n m = sumdiv n == m && sumdiv m == n

o con una funzione ad un solo parametro:

fidanzati :: (Int → Int) → Bool
fidanzati (n,m) = sumdiv n == m && sumdiv m == n

La prima coppia di numeri fidanzati è (48,75): sono i cosiddetti…*promessi sposi*.
E’ possibile implementare una funzione che fornito un limite superiore l restituisca la lista delle coppie di numeri fidanzati le cui componenti siano comprese tra 1 ed l:

numfidanzati :: Int→ [(Int,Int)]
numfidanzati l = [(x,y) | x<-[1..l], y<-[1..l], fidanzati (x,y)]

Sarà il fatto che ormai il pc ha qualche annetto ma è stato interessante fare una prova con un limite pari a 1000 e constatare che ci ha messo un bel po’. :P
E’ interessante notare che anche nella matematica i numeri amici non possono essere fidanzati … ma di questo parleremo un’altra volta.



Bibliografia

Numeri Amicabili. (s.d.). Tratto il giorno Febbraio 15, 2011 da Wikipedia (IT): http://it.wikipedia.org/wiki/Numeri_amicabili
Progetto Polymath - Numeri Socievoli e Numeri Fidanzati. (s.d.). Tratto il giorno Febbraio 18, 2001 da Progetto Polymath: http://areeweb.polito.it/didattica/polymath/htmlS/info/Numeri/Ott06/Numeri_ott06.htm
Scuola Pitagorica. (s.d.). Tratto il giorno Febbraio 15, 2011 da Wikipedia (IT): http://it.wikipedia.org/wiki/Scuola_pitagorica

Category: blog

Tags: haskell

Back






Comments