Track
/
Scala
Scala
/
Esercizi
/
Conteggio dei nucleotidi
Conteggio dei nucleotidi

Conteggio dei nucleotidi

Medio

Istruzioni

Ognuno di noi eredita dai propri genitori biologici una serie di istruzioni chimiche note come DNA, che influenzano il modo in cui il nostro corpo è costruito. Tutta la vita conosciuta dipende dal DNA!

Nota: non hai bisogno di capire nulla di nucleotidi o DNA per completare questo esercizio.

Il DNA è una lunga catena di altre sostanze chimiche, e le più importanti sono i quattro nucleotidi: adenina, citosina, guanina e timina. Una singola catena di DNA può contenere miliardi di questi quattro nucleotidi, e l'ordine in cui compaiono è importante! Chiamiamo l'ordine di questi nucleotidi in un tratto di DNA una «sequenza di DNA».

Rappresentiamo una sequenza di DNA come una raccolta ordinata di questi quattro nucleotidi, e un modo comune per farlo è una stringa di caratteri come "ATTACG" per una sequenza di DNA di 6 nucleotidi. 'A' per l'adenina, 'C' per la citosina, 'G' per la guanina e 'T' per la timina.

Data una stringa che rappresenta una sequenza di DNA, conta quanti nucleotidi di ciascun tipo sono presenti. Se la stringa contiene caratteri che non sono A, C, G o T, allora non è valida e devi segnalare un errore.

Per esempio:

"GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2
"INVALID" -> error

Un uso comune di Either è indicare un calcolo che può potenzialmente produrre un errore (se l'errore in sé non interessa, il tipo più semplice Option potrebbe essere una scelta migliore). In assenza di un errore il risultato è di solito un Right (aiuto mnemonico: il valore «right»), mentre un errore è un Left, per esempio un Left[String] che contiene un messaggio di errore. Nota che in Scala 2.12 Either è right-biased per impostazione predefinita, quindi funziona come previsto per operazioni come filter, map, flatMap o dentro una for-comprehension. Se non hai familiarità con Either, puoi leggere questo tutorial. Tieni però presente che questo tutorial riguarda versioni di Scala precedenti alla 2.12. Per Scala 2.12 puoi tranquillamente ignorare RightProjection e omettere .right. Either è una cosiddetta Monade che copre un «aspetto computazionale», in questo caso la gestione degli errori. L'uso corretto delle monadi può portare a codice molto conciso ma elegante e leggibile. Un uso improprio può facilmente portare al contrario. Guarda questo video per saperne di più.

Errori comuni da evitare

Ci sono alcune regole pratiche per Either:

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

è meglio avere

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

(esiste Either.map per applicare funzioni così semplici, quindi non devi appesantirle con Either).

  1. Non fare «unwrap» se non ne hai davvero bisogno. Spesso esistono funzioni integrate per il tuo scopo. Indicatori di unwrapping prematuro sono isLeft/isRight o il pattern matching. Per esempio, invece di
val x: Either[String, Int] = ...

if (x.isRight) x.right.get + 1 else x.left.get
// or
x match {
  case Right(n) => n + 1
  case Left(s) => s
}

è meglio avere

x fold (identity, _ + 1)
  1. Le monadi si possono usare dentro una for-comprehension, FTW. Questo è consigliabile quando vuoi «comporre» diverse istanze di Either. Invece di
val xo: Either[String, Int] = ...
val yo: Either[String, Int] = ...
val zo: Either[String, 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 Conteggio dei nucleotidi?

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