Hamming

Hamming

Fácil

Introdução

O teu corpo é feito de células que contêm DNA. Essas células desgastam-se regularmente e precisam de ser substituídas, o que conseguem ao dividir-se em células-filhas. De facto, o corpo humano médio passa por cerca de dez mil biliões de divisões celulares ao longo da vida!

Quando as células se dividem, o seu DNA também se replica. Por vezes, durante este processo, acontecem erros e pequenas partes de DNA ficam codificadas com a informação incorreta. Se compararmos duas cadeias de DNA e contarmos as diferenças entre elas, conseguimos ver quantos erros ocorreram. É a isto que se chama a "distância de Hamming".

A distância de Hamming é útil em muitas áreas da ciência, não só na biologia, por isso é uma expressão que vale a pena conheceres :)

Instruções

Calcula a distância de Hamming entre duas cadeias de ADN.

Lemos o ADN através das letras C, A, G e T. Duas cadeias podem ter este aspeto:

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^  ^ ^    ^^

Têm 7 diferenças e, por isso, a distância de Hamming é 7.

Notas de implementação

A distância de Hamming só está definida para sequências de igual comprimento. Por isso, não deve ser possível calculá-la entre sequências com comprimentos diferentes.

O Option usa-se para indicar um cálculo que pode não ter um resultado útil (por exemplo, por causa de um erro ou de dados inválidos). Se não estás familiarizado com o Option, podes ler este tutorial. O Option é uma chamada mónada que abrange um «aspeto computacional», neste caso a possível ausência de um valor. O uso correto das mónadas pode resultar em código muito conciso, mas ainda assim elegante e legível. O uso incorreto pode facilmente resultar no contrário. Vê este vídeo para saberes mais.

Armadilhas comuns que deves evitar

Há algumas regras básicas para o Option:

  1. Se não precisas dele, não o uses. Em vez de
def add1(x: Int): Option[Int] = Some(x + 1)

é melhor ter

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

(há o Option.map para aplicar funções simples como estas, por isso não precisas de as sobrecarregar com o Option). 2. Não faças «unwrap» se não precisares mesmo. Muitas vezes há funções incorporadas para o que queres. Indícios de «unwrap» prematuro são isDefined/isEmpty ou a correspondência de padrões. Em vez de

val x: Option[Int] = ...

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

é melhor ter

x map (_ + 1) getOrElse 0
  1. As mónadas podem ser usadas dentro de uma for-comprehension FTW. Isto é aconselhável quando queres «compor» várias instâncias de Option. Em vez de
val xo: Option[Int] = ...
val yo: Option[Int] = ...
val zo: Option[Int] = ...

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

é melhor ter

for {
  x <- xo
  y <- yo
  z <- zo
} yield x + y + z
Editar via GitHub A ligação abre numa nova janela ou separador
Scala Exercism

Estás pronto para começar Hamming?

Inscreve-te no Exercism para aprenderes e dominares Scala com 95 exercícios, e mentoria humana real, tudo grátis.