일지

JUNGOL...157

niamdank 2021. 11. 3. 10:16

Intermediate_Coder/백트래킹-DFS/DNA 조합


문제                                            

도훈이는 학교에서 배운 유전자 실험을 이용해서 자신만의 실험을 계획하고 있다

(프로그램을 작성해주는 복제인간을 만드는 것이 목표라고 한다).

 

도훈이가 갖고 있는 DNA 조각은 n(2<=n<=7)개가 있다. 

이들 DNA 조각은 복제인간이 가져야 할 중요한 유전자를 담고 있기 때문에,

이 조각들의 정보를 그대로 유지시키면서 가장 짧은 DNA 순열을 새로 만들고 싶다.

 

DNA 순열을 조합하는 과정은 아래와 같다.

 

1) n개의 DNA조각을 임의의 순서로 나열한다.

2) 인접한 두 DNA조각에서 앞쪽 조각의 오른쪽 끝 부분이
   뒤쪽 조각의 왼쪽 끝 부분과 최대한 많이 일치하는 부분을 찾는다.

3) 모든 인접한 두 DNA에서 중복되는 부분을 제거하고 나머지 부분을
   순서대로 모아 새로운 문자열을 만든다.

 

4) 새로운 문자열을 만들때 인접한 문자열의 공통부분만 제거할 수 있음에 유의한다.

   예를 들어 ABC, D, BCD 를 순서대로 연결하는 경우 ABCD가 아닌 ABCDBCD가 된다. 

 

예를 들어, ‘GATTA’와 ‘TACA’는 ‘GATTACA’로 조합될 수 있다. 

왜냐하면 ‘GATTA’의 오른쪽 두 글자 ‘TA’가 ‘TACA’의 왼쪽 두 글자 ‘TA’와 일치하기 때문이다. 

어떤 경우에는 한 조각이 다른 조각의 내용을 모두 포함하고 있을 수도 있고, 어떤 경우에는 단 한 글자도 일치하지 않을 수도 있다.

 

‘GATTACA’와 ‘TTACA’는 완벽하게 겹치는 반면에 ‘GATTACA’와 ‘TTA’는 한 글자도 겹치지 않는다. 

 

아래에 조합의 몇 가지 예가 있다.

GATTA+TACA -> GATTACA

TACA+GATTA -> TACAGATTA

TACA+ACA -> TACA

TAC+TACA -> TACA

ATAC+TACA -> ATACA

TACA+ACAT -> TACAT

 

입력 형식                                     

첫 줄에 n이 입력되고, 두 번째 줄부터 n개의 줄에 걸쳐 각 DNA 조각이 입력된다.
DNA조각의 길이는 1 ~ 7 이다.

 

출력 형식                                     

첫 번째 줄에 n개의 DNA를 모두 조합해서 하나의 DNA 순열로 만들었을 때 최소 길이를 출력한다.

 

입력 예                                        

4                 | 3
GATTA          | ABC
TAGG           | BCD
ATCGA         | ABCD
CGCAT         |

 

출력 예                                        

13              | 4


DNACombination.h

#include <iostream>
#include <string>
#include <algorithm>

using std::string;

class DNACombination : public Base
{
private:
	size_t GetMinLengthOfCombination(string arr[7], int n, string combination = "");
	void CopyArrWithoutIdx(string arr[7], string copyArr[7], int n, int idx);
	string CombineDNA(string originDNA, string addDNA);
};

 

DNACombination.cpp

void DNACombination::Code()
{
	int n;
	std::cin >> n;

	string arr[7];
	for (int i = 0; i < n; i++)
	{
		std::cin >> arr[i];
	}

	std::cout << GetMinLengthOfCombination(arr, n);
}

/// <summary>
/// DNA를 조합할 때 최소 길이가 되는 조합의 길이를 반환한다.
/// </summary>
/// <param name="arr">DNA 배열</param>
/// <param name="n">배열의 길이</param>
/// <param name="combination">조합 결과</param>
/// <returns>조합의 길이</returns>
size_t DNACombination::GetMinLengthOfCombination(string arr[7], int n, string combination)
{
	if (n == 0)
	{
		return combination.size();
	}

	size_t minLength{ 999'999'999 };
	string newArr[7];
	for (int i = 0; i < n; i++)
	{
		CopyArrWithoutIdx(arr, newArr, n, i);
		size_t length{ GetMinLengthOfCombination(newArr, n - 1, CombineDNA(combination, arr[i])) };
		if (length < minLength)
		{
			minLength = length;
		}
	}
	return minLength;
}

/// <summary>
/// 배열의 주어진 인덱스를 제외한 값을 새로운 배열에 복사한다.
/// </summary>
/// <param name="arr">배열</param>
/// <param name="copyArr">복사할 배열</param>
/// <param name="n">배열의 길이</param>
/// <param name="idx">제외할 인덱스</param>
void DNACombination::CopyArrWithoutIdx(string arr[7], string copyArr[7], int n, int idx)
{
	for (int i = 0, j = 0; i < n; i++)
	{
		if (i != idx)
		{
			copyArr[j++] = arr[i];
		}
	}
}

/// <summary>
/// 기존 DNA와 새 DNA를 조합한다.
/// </summary>
/// <param name="originDNA">기존 DNA</param>
/// <param name="addDNA">새로 추가된 DNA</param>
/// <returns>조합된 DNA</returns>
string DNACombination::CombineDNA(string originDNA, string addDNA)
{
	size_t originSize{ originDNA.size() };
	size_t addSize{ addDNA.size() };
	size_t restIdx{ 0 };

	for (size_t i = 0; i < originSize; i++)
	{
		bool notCombined{ false };
		for (restIdx = 0; restIdx < addSize && i + restIdx < originSize; restIdx++)
		{
			// 중간에 다른 값이 있으면 포함되지 않는다.
			if (originDNA[i + restIdx] != addDNA[restIdx])
			{
				notCombined = true;
				break;
			}
		}
        
		// 안에 완전히 넣어지는 경우를 제외한다.
		if (restIdx == addSize && i + restIdx < originSize)
		{
			notCombined = true;
		}

		if (notCombined)
		{
			continue;
		}

		break;
	}

	return originDNA.append(addDNA.substr(restIdx));
}

 


실행 결과 Accepted(90)

원인 중간에 묻히는 경우를 제외했어도 동일한 결과가 출력되었다.

처리 방법 실제 조합된 값과 길이를 출력해 본 결과 정상적으로 동작하는 것 같아 질문을 올려봐야 할 것 같다.


 

출력결과

5
TAG
TGCAG
CA
T
ACTG
TAGTGCAGCATACTG      15
TAGTGCAGCACTGT      14
TAGTGCAGTCACTG      14
TAGTGCAGTACTGCA      15
TAGTGCAGACTGCAT      15
TAGTGCAGACTGTCA      15
TAGCATGCAGTACTG      15
TAGCATGCAGACTGT      15
TAGCATGCAGACTG      14
TAGCATACTGCAG      13
TAGCACTGCAGT      12
TAGCACTGTGCAG      13
TAGTGCAGCACTG      13
TAGTGCAGACTGCA      14
TAGTCATGCAGACTG      15
TAGTCACTGCAG      12
TAGTACTGCAGCA      13
TAGTACTGCAG      11
TAGACTGCAGCAT      13
TAGACTGCAGTCA      13
TAGACTGCAGT      11
TAGACTGCATGCAG      14
TAGACTGTGCAGCA      14
TAGACTGTCATGCAG      15
TGCAGTAGCATACTG      15
TGCAGTAGCACTGT      14
TGCAGTAGTCACTG      14
TGCAGTAGTACTGCA      15
TGCAGTAGACTGCAT      15
TGCAGTAGACTGTCA      15
TGCAGCATAGTACTG      15
TGCAGCATAGACTGT      15
TGCAGCATAGACTG      14
TGCAGCATACTGTAG      15
TGCAGCACTGTAGT      14
TGCAGCACTGTAG      13
TGCAGTAGCACTG      13
TGCAGTAGACTGCA      14
TGCAGTCATAGACTG      15
TGCAGTCACTGTAG      14
TGCAGTACTGTAGCA      15
TGCAGTACTGCATAG      15
TGCAGACTGTAGCAT      15
TGCAGACTGTAGTCA      15
TGCAGACTGCATAGT      15
TGCAGACTGCATAG      14
TGCAGACTGTAGCA      14
TGCAGACTGTCATAG      15
CATAGTGCAGTACTG      15
CATAGTGCAGACTGT      15
CATAGTGCAGACTG      14
CATAGTACTGCAG      13
CATAGACTGCAGT      13
CATAGACTGTGCAG      14
CATGCAGTAGTACTG      15
CATGCAGTAGACTGT      15
CATGCAGTAGACTG      14
CATGCAGTACTGTAG      15
CATGCAGACTGTAGT      15
CATGCAGACTGTAG      14
CATAGTGCAGACTG      14
CATAGACTGCAG      12
CATGCAGTAGACTG      14
CATGCAGACTGTAG      14
CATACTGTAGTGCAG      15
CATACTGCAGTAG      13
CACTGTAGTGCAGT      14
CACTGTAGTGCAG      13
CACTGCAGTAGT      12
CACTGCAGTAG      11
CACTGTAGTGCAG      13
CACTGTGCAGTAG      13
TAGTGCAGCACTG      13
TAGTGCAGACTGCA      14
TAGCATGCAGACTG      14
TAGCACTGCAG      11
TAGACTGCAGCA      12
TAGACTGCAG      10
TGCAGTAGCACTG      13
TGCAGTAGACTGCA      14
TGCAGCATAGACTG      14
TGCAGCACTGTAG      13
TGCAGACTGTAGCA      14
TGCAGACTGCATAG      14
TCATAGTGCAGACTG      15
TCATAGACTGCAG      13
TCATGCAGTAGACTG      15
TCATGCAGACTGTAG      15
TCACTGTAGTGCAG      14
TCACTGCAGTAG      12
TACTGTAGTGCAGCA      15
TACTGTAGCATGCAG      15
TACTGCAGTAGCA      13
TACTGCAGCATAG      13
TACTGCATAGTGCAG      15
TACTGCAGTAG      11
ACTGTAGTGCAGCAT      15
ACTGTAGTGCAGTCA      15
ACTGTAGCATGCAGT      15
ACTGTAGCATGCAG      14
ACTGTAGTGCAGCA      14
ACTGTAGTCATGCAG      15
ACTGCAGTAGCAT      13
ACTGCAGTAGTCA      13
ACTGCAGCATAGT      13
ACTGCAGCATAG      12
ACTGCAGTAGCA      12
ACTGCAGTCATAG      13
ACTGCATAGTGCAGT      15
ACTGCATAGTGCAG      14
ACTGCAGTAGT      11
ACTGCAGTAG      10
ACTGCATAGTGCAG      14
ACTGCATGCAGTAG      14
ACTGTAGTGCAGCA      14
ACTGTAGCATGCAG      14
ACTGTGCAGTAGCA      14
ACTGTGCAGCATAG      14
ACTGTCATAGTGCAG      15
ACTGTCATGCAGTAG      15
10

 

NadanKim/CodingTest_JUNGOL: JUNGOL 코딩 테스트를 위한 저장소 (github.com)

 

NadanKim/CodingTest_JUNGOL

JUNGOL 코딩 테스트를 위한 저장소. Contribute to NadanKim/CodingTest_JUNGOL development by creating an account on GitHub.

github.com