title: Programmers - 브라이언의 고민
date: 2022-08-31
tags:
- Algorithm
https://school.programmers.co.kr/learn/courses/30/lessons/1830
문제 요약
기존의 단어에 여러 규칙을 적용하여 새로운 문자열을 만들어 광고를 하는 것을 발견하였다.
각 문자열의 기존 문자열을 찾아낼 수 있다면 해당 문자열을, 규칙에 부합하면 "invalid"를 return한다.
문제 풀이
약 한달 전에 시도하였다가 실패한 문제이다.
조금 더 general하게 함수를 선언한 후, 함수를 적극적으로 이용하여 문제를 풀어 예외 처리가 되는 케이스를 최대한 줄이고자 하였다.
소문자의 개수를 전부 센다. 2개일 경우 두 규칙 모두 적용이 가능할 수 있으며, 이외의 경우에는 1번 규칙만 적용할 수 있다.
우선 소문자의 개수가 2개가 아닌 소문자에 대하여 1번 규칙을 적용한다.
2개씩의 동일한 간격이어야 하며, 이 때는 오로지 단어를 구성하는 대문자만 존재하여야 한다.
1번 규칙을 적용가능할 때 이를 적용하고, 적용한 단어의 양끝에 .
을 붙인다.
공백으로 붙여도 되나, 이 문제에서 공백은 일반적으로 서로 다른 단어임을 나타낼 때 사용하였다.
1번 규칙을 적용한 단어에 2번 규칙을 적용할 수 있기에, 이를 구분하기 위하여 다른 문자를 사용하였다.
이후 남은 소문자에 대하여 2번 규칙을 적용한다.AqSwDwFqG
와 같은 경우 w
에 대해서 1번 규칙, q
에 대해서 2번 규칙을 적용하면 올바른 문자열을 만들어낼 수 있다.
아마 과거에는 이러한 경우를 생각하지 않고 전부 2번 규칙을 적용하여 틀린 것으로 추측이 된다..
의 개수와 위치 또한 중요하기에 이를 따로 count하며, 소문자가 발견되면 우선 1번 규칙을 적용한다.
1번 규칙을 적용하여 남은 소문자가 없고, .
의 처리 또한 정상적으로 이루어지면 이 단어에 2번 규칙을 적용한다.
모든 규칙을 적용한다면 공백이 매우 많은 문자열이 생긴다. 불필요한 공백을 없애준 후, 만들어진 광고 문구를 return한다.
이 문제를 풀었던 것이 큰 도움이 되었다.
함수를 미리 잘 구성하였다면 어디서든 이 함수를 사용할 수 있어야 한다.
이 덕분에 2번 규칙을 적용하던 중 1번 규칙을 적용할 수 있었다.
프로그램
#include <string>
#include <vector>
using std :: string ;
using std :: vector ;
string strGetRule1 ( string & strAnswer , int iStartIndex , int iCount )
{
string strReturn = "" ;
for ( int i = 0 ; i < iCount + 1 ; ++i )
{
strReturn += strAnswer [ iStartIndex + ( i << 1 ) - 1 ] ;
if ( ' ' == strReturn [ i ] ) // Empty space must not be here
return "invalid" ;
if ( ( 'a' <= strReturn [ i ] ) && ( strReturn [ i ] <= 'z' ) ) // Small letter must not be here
return "invalid" ;
}
return strReturn ;
}
bool bAdoptRule1 ( string & strAnswer , char cTarget , int iCount )
{
int iStringSize = strAnswer.size () ;
int iStartIndex = -1 ;
int iFormerIndex ;
int iCheckCount = 0 ;
for ( int i = 0 ; ( i < iStringSize ) && ( iCheckCount < iCount ); ++i )
{
if ( cTarget == strAnswer [ i ] )
{
if ( -1 == iStartIndex )
{
iStartIndex = i ;
iFormerIndex = i ;
}
else
{
if ( 2 != i - iFormerIndex ) // Gap must be 2
return false ;
else
iFormerIndex = i ;
}
++ iCheckCount ;
}
else if ( ( -1 != iStartIndex ) && ( ( 'A' > strAnswer [ i ] ) || ( strAnswer [ i ] > 'Z' ) ) )
return false ;
}
if ( ( 0 == iStartIndex ) || ( iFormerIndex + 1 == iStringSize ) ) // Must letter at front and back
return false ;
if ( ( ( 'A' > strAnswer [ iStartIndex - 1 ] ) || ( strAnswer [ iStartIndex - 1 ] > 'Z' ) )
|| ( ( 'A' > strAnswer [ iFormerIndex + 1 ] ) || ( strAnswer [ iFormerIndex + 1 ] > 'Z' ) ) )
return false ;
string strRule1 = strGetRule1 ( strAnswer , iStartIndex , iCount ) ;
if ( 0 == strRule1.compare ( "invalid" ) ) // Found empty space or small letter, can't adopt rule1
return false ;
strAnswer = strAnswer.substr ( 0 , iStartIndex - 1 ) + "." + strGetRule1 ( strAnswer , iStartIndex , iCount ) + "." + strAnswer.substr ( iFormerIndex + 2 , iStringSize - iFormerIndex - 2 ) ;
return true ;
}
bool bAdoptRule2 ( string & strAnswer , char cTarget , vector < int > & vAlphabetCount )
{
vAlphabetCount [ cTarget - 'a' ] = 0 ;
int iStartIndex = -1 ;
int iEndIndex = -1 ;
int iLeftDotIndex = -1 ;
int iRightDotIndex = -1 ;
int iStringSize = strAnswer.size () ;
for ( int i = 0 ; i < iStringSize ; ++i )
{
if ( cTarget == strAnswer [ i ] )
{
if ( -1 == iStartIndex )
iStartIndex = i ;
else
{
iEndIndex = i ;
break ;
}
}
else if ( ( -1 != iStartIndex ) && ( '.' == strAnswer [ i ] ) )
{
if ( ( -1 == iLeftDotIndex ) && ( iStartIndex + 1 == i ) )
iLeftDotIndex = i ;
else if ( ( -1 != iLeftDotIndex ) && ( -1 == iRightDotIndex ) )
iRightDotIndex = i ;
else // Other condition not exist
return false ;
}
else if ( ( -1 != iStartIndex ) && ( ' ' == strAnswer [ i ] ) ) // Empty space must not be here
return false ;
else if ( ( -1 != iStartIndex ) && ( 'a' <= strAnswer [ i ] ) && ( strAnswer [ i ] <= 'z' ) ) // This must be rule1, or wrong string
{
vAlphabetCount [ strAnswer [ i ] - 'a' ] = 0 ;
if ( ! bAdoptRule1 ( strAnswer , strAnswer [ i ] , 2 ) ) // If false, can't adopt rule1
return false ;
i -= 2 ;
}
}
if ( iStartIndex + 1 == iEndIndex )
return false ;
if ( ( -1 != iLeftDotIndex ) && ( ( -1 == iRightDotIndex )
|| ( iRightDotIndex + 1 != iEndIndex ) ) )
return false ;
strAnswer = strAnswer.substr ( 0 , iStartIndex ) + " " + strAnswer.substr ( iStartIndex + 1 , iEndIndex - iStartIndex - 1 ) + " " + strAnswer.substr ( iEndIndex + 1 , iStringSize - iEndIndex - 1 ) ;
return true ;
}
string strRemoveSpace ( string strAnswer )
{
string strReturn = "" ;
int iEmptySpaceIndex = -1 ;
int iStringSize = strAnswer.size () ;
for ( int i = 0 ; i < iStringSize ; ++i )
{
if ( ( 'a' <= strAnswer [ i ] ) && ( strAnswer [ i ] <= 'z' ) )
return "invalid" ;
else if ( ( -1 == iEmptySpaceIndex ) && ( ( ' ' == strAnswer [ i ] ) || ( '.' == strAnswer [ i ] ) ) )
{
iEmptySpaceIndex = i ;
}
else if ( ( 'A' <= strAnswer [ i ] ) && ( strAnswer [ i ] <= 'Z' ) )
{
if ( 0 < iEmptySpaceIndex )
{
strReturn += ' ' ;
}
iEmptySpaceIndex = -1 ;
strReturn += strAnswer [ i ] ;
}
}
return strReturn ;
}
string solution ( string sentence )
{
string answer = sentence ;
vector < int > vAlphabetCount ( 26 , 0 ) ;
int iSentenceSize = sentence.size () ;
const char * cpSentence = sentence.data () ;
for ( int i = 0 ; i < iSentenceSize ; ++i )
{
if ( ( 'a' <= cpSentence [ i ] ) && ( cpSentence [ i ] <= 'z' ) ) // Small letter
{
++ vAlphabetCount [ cpSentence [ i ] - 'a' ] ;
}
else if ( ' ' == cpSentence [ i ] ) // Empty space must be deleted
return "invalid" ;
}
for ( int i = 0 ; i < 26 ; ++i )
{
if ( ( 0 != vAlphabetCount [ i ] ) && ( 2 != vAlphabetCount [ i ] ) ) // Only rule 1
{
if ( ! bAdoptRule1 ( answer , 'a' + i , vAlphabetCount [ i ] ) ) // If false, can't adopt rule1
return "invalid" ;
}
}
for ( int i = 0 ; i < 26 ; ++i )
{
if ( 2 == vAlphabetCount [ i ] )
{
if ( ! bAdoptRule2 ( answer , 'a' + i , vAlphabetCount ) ) // If false, can't adopt rule2
return "invalid" ;
}
}
return strRemoveSpace ( answer ) ;
}
'Judge' 카테고리의 다른 글
Programmers - 매칭 점수 (0) | 2022.09.19 |
---|---|
Programmers - 징검다리 건너기 (0) | 2022.09.06 |
Programmers - 경주로 건설 (0) | 2022.08.30 |
Programmers - 야근 지수 (0) | 2022.08.28 |
Programmers - 최적의 행렬 곱셈 (0) | 2022.08.27 |