본문 바로가기
Kotlin/Exercise

Hamming -DNA 차이

by 봄석 2019. 3. 3.

Hamming -DNA 차이


두 DNA 가닥의 해밍 차이를 계산해보는 테스트입니다.

돌연변이는 단순히 핵산, 특히 DNA 생성 또는 복제과정에서 발생하는 실수입니다. 핵산은 세포기능에 필수적이기 때문에 돌연변이는 세포 전체에 파급효과를 일으키는 경향이 있습니다. 돌연변이는 기술적으로 실수이지만, 매우 드문 돌연변이는 세포에 유익한 특성을 부여할 수 있습니다. 


공통 조상과 함께 서로다른 게놈으로 부터 얻은 2개의 상동 DNA 가닥 사이의 차이 수를 세어 두 가닥 사이의 진화경로에서 발생할수 있는 돌연변이의 최소 수를 측정합니다


이를 해밍거리(Hamming distance)라고 합니다.


GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^  ^ ^    ^^


위의 DNA가닥 사이의 해밍거리는 7입니다 .



@

TestCode

class HammingTest {
 
    @Rule
    @JvmField
    var expectedException: ExpectedException = ExpectedException.none()
 
 
    @Test
    fun noDistanceBetweenEmptyStrands() {
        assertEquals(0, Hamming.compute(""""))
    }
 
 
    @Test
    fun noDistanceBetweenShortIdenticalStrands() {
        assertEquals(0, Hamming.compute("A""A"))
    }
 
 
    @Test
    fun noDistanceBetweenLongIdenticalStrands() {
        assertEquals(0, Hamming.compute("GGACTGA""GGACTGA"))
    }
 
 
    @Test
    fun completeDistanceInSingleNucleotideStrand() {
        assertEquals(1, Hamming.compute("A""G"))
    }
 
 
    @Test
    fun completeDistanceInSmallStrand() {
        assertEquals(2, Hamming.compute("AG""CT"))
    }
 
 
    @Test
    fun smallDistanceInSmallStrand() {
        assertEquals(1, Hamming.compute("AT""CT"))
    }
 
 
    @Test
    fun smallDistanceInMediumStrand() {
        assertEquals(1, Hamming.compute("GGACG""GGTCG"))
    }
 
 
    @Test
    fun smallDistanceInLongStrand() {
        assertEquals(2, Hamming.compute("ACCAGGG""ACTATGG"))
    }
 
    @Test
    fun nonUniqueCharacterInFirstStrand() {
        assertEquals(1, Hamming.compute("AAG""AAA"))
    }
 
    @Test
    fun nonUniqueCharacterInSecondStrand() {
        assertEquals(1, Hamming.compute("AAA""AAG"))
    }
 
    @Test
    fun sameNucleotidesInDifferentPositions() {
        assertEquals(2, Hamming.compute("TAG""GAT"))
    }
 
    @Test
    fun largeDistanceInPermutedStrand() {
        assertEquals(4, Hamming.compute("GATACA""GCATAA"))
    }
 
    @Test
    fun largeDistanceInOffByOneStrand() {
        assertEquals(9, Hamming.compute("GGACGGATTCTG""AGGACGGATTCT"))
    }
 
    @Test
    fun validatesFirstStrandNotLonger() {
        expectedException.expect(IllegalArgumentException::class.java)
        expectedException.expectMessage("left and right strands must be of equal length.")
 
        Hamming.compute("AATG""AAA")
    }
 
    @Test
    fun validatesSecondStrandNotLonger() {
        expectedException.expect(IllegalArgumentException::class.java)
        expectedException.expectMessage("left and right strands must be of equal length.")
 
        Hamming.compute("ATA""AGTG")
    }
 
}



JUnit의 Rule이란?  - @Rule 

  • Rule은 테스트 클래스에서 동작 방식을 재정의 하거나 쉽게 추가하는 것을 가능하게 합니다.
  • 사용자는 기존의 Rule을 재사용하거나 확장하는 것이 가능합니다

JUnit의 Rule 또는 CustomRule - https://nesoy.github.io/articles/2018-12/Junit-Rule


@JvmField란 ?

 @JvmField는 getter/setter의 생성을 방지하는 어노테이션입니다.



해결 1) throwException, forEach를 사용한 해결방안

object Hamming {
    
        fun compute(input1: String, input2: String): Int {
            var count = 0
            var index = 0
            if(input1.length!=input2.length)
                throw IllegalArgumentException("left and right strands must be of equal length.")
            input1.forEach {
                if (it != input2[index])
                    count++
                index++
            }
            return count
 
        }
    }


input1과 input2의 사이즈가 다르면 IllegalArgumentException을 던지고 

input의 배열을 순회하며 input2[index]와 비교하여  내용이 다르다면 count를 증가시킨다.


해결 2) zip, count ,require를 사용한 해결방안

 object Hamming {
        fun compute(dna1: String, dna2: String): Int {
            require(dna1.length == dna2.length) { "left and right strands must be of equal length." }
            return dna1.zip(dna2).count { it.first != it.second }
      }
    }



zip 함수는

infix fun CharSequence.zip(
    other: CharSequence
)List<Pair<Char, Char>>

val stringA = "abcd"
 
val stringB = "zyx"
 
val result = stringA.zip(stringB) { a, b -> "$a$b" }
 

println(result) // [az, by, cx]

위와같이 같은인덱스의 스트링을 비교하여 List<Pair<Char,Char>를 리턴합니다.

그리고 Pair의 first와 second를 비교하여 다른 것의 개수를 리턴합니다.






코틀린 공식문서 zip - https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/zip.html

코틀린 공식문서 count - https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/count.html

'Kotlin > Exercise' 카테고리의 다른 글

Twofer - 스트링 리턴하기  (2) 2019.03.03
윤년 찾기  (4) 2019.03.03
영어에서 돼지 라틴어로 번역하기  (2) 2019.02.24
Isogram인지아닌지 판단하기  (2) 2019.02.24
Raindrop - 숫자를 문자열로 변환하기  (2) 2019.02.23

댓글