Languages/Java

[자바 왕기초] 05. 배열

Dev다D 2021. 1. 19. 19:56
반응형

04. DNA 염기 서열 분석

실습 과제

 

DNA 염기 서열은 생물의 유전 성질을 결정하는 매우 중요한 역할을 가지고 있습니다. 템플릿에 주어진 염기 서열에서 TAGG, CCAG, AGCC가 총 몇 번 등장하는지 세어봅시다.

만약 TAGG가 2번, CCAG가 4번, AGCC가 3번 등장한다면 아래와 같은 출력 값이 나옵니다.

 

> TAGG: 2

CCAG: 4

AGCC: 3


public class Dna {
    public static void main(String[] args) {
        String dna = "GATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGTGTGAGCCA"
                + "CCACGCCCGGCTAATTTTTATTTATTTATTTAAAGACAGAGTCTCACTCT"
                + "GTCACTCAGGCTAGAGTGCAGTGGCACCATCTCAGCTCACTGCAGCCTTG"
                + "ACCTCCCTGGGCTCCGGTGATTTCACCCTCCCAAGTAGCTAGGACTACAG"
                + "GCACATGCCACGACACCCAGCTAATTTTTTATTTTCTGTGAAGTCAAGGT"
                + "CTTGCTACGTTGCCCATGCTGGTATCAAACCCCTGGGCTCAATCAATCCT"
                + "TCCACCTCAGCCTCCCCAAGTATTGGGGTTACAGGCATGAGCTACCACAC"
                + "TCAGCCCTAGCCTACTTGAAACGTGTTCAGAGCATTTAAGTTACCCTACA"
                + "GTTGGGCAAAGTCATCTAACACAAAGCCCTTTTTATAGTAATAAAATGTT"
                + "GTATATCTCATGTGATTTATTGAATATTGTTACTGAAAGTGAGAAACAGC"
                + "ATGGTTGCATGAAAGGAGGCACAGTCGAGCCAGGCACAGCCTGGGCGCAG"
                + "AGCGAGACTCAAAAAAAGAAAAGGCCAGGCGCACTGGCTCACGCCTGTAA"
                + "TCCCAGCATTTCGGGAGGCTGAGGCGGGTGGATCACCTGAGGTCAGGAGT"
                + "TCAAGACCAGCCTAGCCAACATGGTGAAACCCCGTCTCTACTAAAATACA"
                + "AAAATTAACCGGGCGTGATGGCAGGTGCCTGTAATCCCAGCTACTTGGGA"
                + "GGCTGAGGCAGGAGAATCGCTTGAACCAGGAGGCGGAGGTTGCAGGGAGC"
                + "CAAGATGGCGCCACTGCACTCCAGCCTGGGCGATAGAGTGAGACTCCGTC"
                + "TCAGAAAAAAAAGAAAAGAAACGAGGCACAGTCGCATGCACATGTAGTCC"
                + "CAGTTACTTGAGAGGCTAAGGCAGGAGGATCTCTTGAGCCCAAGAGTTTG"
                + "AGTCCAGCCTGAACAACATAGCAAGACATCATCTCTAAAATTTAAAAAAG"
                + "GGCCGGGCACAGTGGCTCACACCTGTAATCCCAGCACTTTGGGAGGTGGA"
                + "GGTGGGTAGATCACCTGACGTCAGGAGTTGGAAACCAGCCTGGCTAACAT";
        char[] charArray = dna.toCharArray();
        int TAGG = 0;
        int CCAG = 0;
        int AGCC = 0;

        char[] current = new char[4];

        for (int i = 0; i < charArray.length - 3; i++) {
            for (int k = 0; k < current.length; k++) {
                current[k] = charArray[i + k];
            }
            String seq = new String(current);

            switch (seq) {
                case "TAGG":
                    TAGG++;
                    break;
                case "CCAG":
                    CCAG++;
                    break;
                case "AGCC":
                    AGCC++;
                    break;
            }
        }
        System.out.println("TAGG: " + TAGG);
        System.out.println("CCAG: " + CCAG);
        System.out.println("AGCC: " + AGCC);
    }
}

 

1. 일단 TAGG, CCAG, AGCC가 각각 몇 개씩 있는지 담을 변수가 필요합니다.

// TAGG, CCAG, AGCC
int TAGG = 0;
int CCAG = 0;
int AGCC = 0;

 

2. charArray를 탐색할 for문을 만들어 줍니다. (반복문)

for (int i = 0; i < charArray.length - 3; i++) {
    
}

 눈 여겨 볼 점은 두 가지입니다. int i = 0에서 시작한 것과, i < charArray.length - 3까지만 탐색한다는 점입니다.

문자열의 첫 줄("GATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGTGTGAGCCA")을 보세요. 우린 이 문자열을 "GATC"(인덱스 0~3), "ATCC"(인덱스 1~4), "TCCG"(2~5), "CCGC"(3~6), ... 이런 식으로 확인합니다. 그러다가 맨 마지막 줄("GGTGGGTAGATCACCTGACGTCAGGAGTTGGAAACCAGCCTGGCTAACAT")에서 "ACAT"까지만 확인해야겠죠? "ACAT"은 인덱스 length - 4부터 length - 1까지이기 때문에 종결식을 i < charArray.length - 3으로 잡으면 됩니다!

 

3. for문의 수행 부분에 들어갈 때마다 검사할 문자 4개를 담을 4칸짜리 문자 배열(char[])을 선언합니다. (길이 4인 염기서열 형성)

for (int i = 0; i < charArray.length - 3; i++) {
    char[] current = new char[4];
}

for문 안에서 배열을 선언하는 이유는 반복문을 벗어나면 더 이상 쓸 일이 없기 때문입니다.

하지만, 다른 관점에서 생각해 볼 수도 있습니다. 배열을 새로 만드는 작업의 비용이 클 수 있기 때문에, 여러 번 반복하며 만들지 않고 for문 밖에서 한 번만 만들고 재사용하는 것이 나을 수도 있습니다.

char[] current = new char[4];
for (int i = 0; i < charArray.length - 3; i++) {
  
}

안에서 만들어야 하는 경우와 밖에서 만들어야 하는 경우에 대한 차이를 설명하고자 두 가지 방식을 다 보여드렸는데요. 최종적으로는 for문 밖에서 배열을 만드는 것으로 하겠습니다.

그 다음은 반복문 내에 또 반복문을 만들어 검사해야 할 문자열 4개를 순서대로 채워 넣습니다.

char[] current = new char[4];
for (int i = 0; i < charArray.length - 3; i++) {
  for (int j = 0; j < current.length; j++) {
    current[j] = charArray[i + j];
  }
}

current 배열의 0번 부터 3번까지를, charArray 배열의 i + 0 번부터 i + 3 번 까지 채워 넣으면 되겠죠?

예를 들어 i = 2일 때,

current[0] = charArray[2]; // T
current[1] = charArray[3]; // C
current[2] = charArray[4]; // C
current[3] = charArray[5]; // G

이렇게 되는 거죠! 이제 채워넣은 current 배열을 가지고 우리가 찾는 염기서열을 세어봅시다.

char[] current = new char[4];
for (int i = 0; i < charArray.length - 3; i++) {
    for (int j = 0; j < current.length ; j++) {
        current[j] = charArray[i + j];
    }
    
    // char[]을 String으로 변환
    // 예: ['a', 'b', 'c', 'd'] => "abcd"
    String seq = new String(current);
}

이렇게 문자열로 변환시키는 이유는 switch문의 변수로 문자열을 사용할 수 있기 때문입니다. 문자 배열 자체로도 검사할 수 있지만 코드가 너무 길어지겠죠?

 

4. switch문을 이용해서 염기서열을 세면 됩니다. (염기서열 세기)

switch (seq) {
  case "TAGG":
    tagg++;
    break;
  case "CCAG":
    ccag++;
    break;
  case "AGCC":
    agcc++;
    break;
}

해당 케이스를 찾으면 각각 염기서열을 찾은 개수를 보관하는 변수에 1을 추가해주면 됩니다.

 


본 내용은 Codeit의  '자바 기초' 강의를
참고하여 작성한 내용입니다.

 

반응형