Hamming

Hamming

쉬움

소개

우리 몸은 DNA를 담고 있는 세포로 이루어져 있어요. 이 세포들은 주기적으로 닳아서 교체가 필요한데, 딸세포로 분열하면서 스스로를 교체해요. 실제로 평균적인 사람의 몸은 평생 동안 약 10,000조 번의 세포 분열을 겪어요!

세포가 분열할 때는 DNA도 함께 복제돼요. 때때로 이 과정에서 실수가 생겨 DNA 조각 하나하나에 잘못된 정보가 담기기도 해요. DNA 두 가닥을 비교해서 서로 다른 부분을 세어 보면 실수가 몇 번 일어났는지 알 수 있어요. 이것을 "해밍 거리"라고 해요.

해밍 거리는 생물학뿐만 아니라 과학의 여러 분야에서 유용하게 쓰여서, 알아 두면 좋은 용어예요 :)

지침

두 DNA 가닥 사이의 해밍 거리를 계산해요.

DNA는 C, A, G, T 네 글자로 읽어요. 두 가닥은 다음과 같이 생겼을 수 있어요:

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^  ^ ^    ^^

두 가닥에는 7개의 차이가 있어요. 따라서 해밍 거리는 7이에요.

구현 참고 사항

해밍 거리는 길이가 같은 서열에 대해서만 정의돼요. 따라서 길이가 다른 서열 사이에서는 계산할 수 없어요.

Option은 유용한 결과가 없을 수도 있는 계산을 나타낼 때 사용해요 (예를 들어 오류나 잘못된 입력 때문일 수 있어요). Option이 낯설다면 이 튜토리얼을 읽어봐요. Option은 이른바 모나드로, "계산적 측면"을 다뤄요. 여기서는 값이 없을 가능성 말이에요. 모나드를 제대로 사용하면 아주 간결하면서도 우아하고 읽기 좋은 코드를 만들 수 있어요. 잘못 사용하면 반대로 되기 십상이죠. 더 알아보려면 이 영상을 봐요.

피해야 할 흔한 함정

Option에는 몇 가지 경험칙이 있어요:

  1. 필요하지 않다면 쓰지 마세요. 이렇게 쓰기보다는
def add1(x: Int): Option[Int] = Some(x + 1)

이렇게 쓰는 게 더 좋아요

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

(이런 단순한 함수를 적용할 때는 Option.map이 있으니, 굳이 Option으로 코드를 어지럽힐 필요가 없어요.) 2. 정말 필요하지 않다면 "unwrap"하지 마세요. 원하는 목적에 딱 맞는 내장 함수가 있는 경우가 많아요. 성급하게 값을 꺼내고 있다는 신호는 isDefined/isEmpty나 패턴 매칭이에요. 이렇게 쓰기보다는

val x: Option[Int] = ...

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

이렇게 쓰는 게 더 좋아요

x map (_ + 1) getOrElse 0
  1. 모나드는 for 컴프리헨션 안에서 쓰면 아주 좋아요. 여러 Option 인스턴스를 "조합"하고 싶을 때 이 방법이 좋아요. 이렇게 쓰기보다는
val xo: Option[Int] = ...
val yo: Option[Int] = ...
val zo: Option[Int] = ...

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

이렇게 쓰는 게 더 좋아요

for {
  x <- xo
  y <- yo
  z <- zo
} yield x + y + z
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Scala Exercism

Hamming 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Scala 트랙을 연습 문제 95개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.