Hamming

Hamming

Facile

Introduzione

Il tuo corpo è fatto di cellule che contengono il DNA. Queste cellule si usurano regolarmente e devono essere sostituite: ci riescono dividendosi in cellule figlie. Anzi, il corpo umano medio va incontro a circa 10 milioni di miliardi di divisioni cellulari nel corso della vita!

Quando le cellule si dividono, si replica anche il loro DNA. A volte, durante questo processo, capita qualche errore e singoli pezzi di DNA vengono codificati con l'informazione sbagliata. Se confrontiamo due filamenti di DNA e contiamo le differenze tra loro, possiamo vedere quanti errori si sono verificati. Questa grandezza è nota come «distanza di Hamming».

La distanza di Hamming è utile in molti ambiti della scienza, non solo in biologia: è quindi una bella espressione da conoscere :)

Istruzioni

Calcola la distanza di Hamming tra due filamenti di DNA.

Il DNA si legge usando le lettere C, A, G e T. Due filamenti potrebbero apparire così:

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^  ^ ^    ^^

Hanno 7 differenze, quindi la distanza di Hamming è 7.

Note sull'implementazione

La distanza di Hamming è definita solo per sequenze di uguale lunghezza: calcolarla tra sequenze di lunghezza diversa non dovrebbe funzionare.

Option si usa per indicare un calcolo che potrebbe non avere un risultato utile (per esempio a causa di un errore o di un input non valido). Se non conosci Option, puoi leggere questo tutorial. Option è una cosiddetta Monad che copre un «aspetto computazionale», in questo caso la possibile assenza di un valore. Un uso corretto delle Monad può portare a un codice molto conciso ma elegante e leggibile. Un uso scorretto può facilmente portare all'opposto. Guarda questo video per saperne di più.

Insidie comuni da evitare

Ci sono alcune regole pratiche per Option:

  1. Se non ti serve, non usarlo. Invece di
def add1(x: Int): Option[Int] = Some(x + 1)

meglio avere

def add1(x: Int): Int = x + 1

(esiste Option.map per applicare funzioni così semplici, quindi non devi appesantirle con Option). 2. Non fare «unwrap» se non ne hai davvero bisogno. Spesso ci sono funzioni integrate che fanno al caso tuo. Indicatori di un unwrap prematuro sono isDefined/isEmpty o il pattern matching. Invece di

val x: Option[Int] = ...

if (x.isDefined) x.get + 1 else 0
// or
x match {
  case Some(n) => n + 1
  case None => 0
}

meglio avere

x map (_ + 1) getOrElse 0
  1. Le Monad si possono usare dentro una for-comprehension, ottimo. Questo è consigliabile quando vuoi «comporre» più istanze di Option. Invece di
val xo: Option[Int] = ...
val yo: Option[Int] = ...
val zo: Option[Int] = ...

xo.flatMap(x =>
  yo.flatMap(y =>
    zo.map(z =>
	  x + y + z)))

meglio avere

for {
  x <- xo
  y <- yo
  z <- zo
} yield x + y + z
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Scala Exercism

Vuoi iniziare Hamming?

Iscriviti a Exercism per imparare e padroneggiare Scala con 95 esercizi e il mentoring di persone reali, tutto gratis.