본문 바로가기

알고리즘/프로그래머스

[1일 1알고리즘] 프로그래머스 - 신규 아이디 추천

https://programmers.co.kr/learn/courses/30/lessons/72410

 

코딩테스트 연습 - 신규 아이디 추천

카카오에 입사한 신입 개발자 네오는 "카카오계정개발팀"에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. "네오"에게 주어진 첫 업무는 새로

programmers.co.kr

주말에는 문제풀이보다는 주중에 풀었던 문제를 복습해보겠습니다

 

해당 문제는 문자열을 문제로직에 맞게 잘 가공하는데 있습니다. 문제자체의 어려움 보다는 풀이 과정의 단계가 많고 내가 코딩할 언어에 대한 문자(열)에 대한 정확한 이해없이는 정답을 맞추기는 힘듭니다.

 

다음은 각 단계에 대한 수도코드입니다.

 

1단계) new_id의 모든 대문자를 대응되는 소문자로 치환합니다.

function step1( new_id ) {
	set output은 공백
    for( new_id의 길이만큼 반복 ) {
    	if( new_id의 i번째 문자가 대문자이면)
        	new_id의 i번째 문자를 소문자로 만들고 output 뒤에 붙임.
        else
        	output 뒤에 new_id번째 문자를 붙임.
   }
return output
}

2단계) new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.

function step2( input ){
	set 문자열 output은 공백
    for ( 문자열 input 길이만큼 ) {
    	if(문자열 input의 i번째 문자가 소문자거나 숫자거나 -,_,. 이면)
        	문자열 output 뒤에 input의 i번째 문자를 붙힘.
        else
        	continue
    }
    return output

3단계) new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.

function step3( input ) {
	set 문자열 output 은 공백, bool형 flag는 false
    for(문자열 input의 길이만큼 반복) {
    	if(문자열 input의 i번째 문자가 마침표(.)이고){
            if(flag 가 false이면){
            	output 뒤에 input 의 i번째 문자를 붙힘.
                set flag is true
            }else
            	continue
        }else{
        	if(flag is true)
            	set flag is false
            output 뒤에 input의 i번째 문자를 붙힘.
        }
   return output
}

4단계) new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.

function step4 ( input ) {
	set output은 공백
    for(input 길이만큼 반복) {
    	if(첫번째 또는 마지막번째이면서 i번째 input 문자가 마침표(.)이면)
        	continue
        output 뒤에 i번째 input 문자를 붙힘.
    }
    return output
}

5단계) new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.

function step5( input ) {
 if(input이 공백이면)
 	return 문자열 a
 return 문자열 input
}

6단계) new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
     만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.

function step6(input) {
	set output은 공백
    if(input의 길이가 15초과이면){
    	for(0 to 14){
        	if(i가 14이고 input의 i번째 문자가 마침표(.)이면)
            	break
            output 뒤에 input의 i번째 문자를 붙힘.
        }
        return output
    }
    return input
}

7단계) new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

function step7( input ) {
	if(input의 길이가 2이하이면){
    	set len은 input의 길이, output은 input
        while(input 길이가 3이 될때까지 반복){
        	output뒤에 input의 마지막 문자를 붙힘
            len <- len + 1
        }
        return output
   }
   return input

아래는 정답코드입니다.(코딩은 꼭 자기힘으로 하시길 바랍니다. 참고용으로만 보세요)

더보기
class Solution {
    public String solution(String new_id) {
        String answer = "";
        answer = step1(new_id);
        answer = step2(answer);
        answer = step3(answer);
        answer = step4(answer);
        answer = step5(answer);
        answer = step6(answer);
        answer = step7(answer);
        return answer;
    }
    
   private static String step1(String new_id){
	        String output = "";
	        for(int i = 0 ; i<new_id.length(); i++){
	            if(new_id.charAt(i) >= 'A' && new_id.charAt(i) <= 'Z')
	                output += (char)(new_id.charAt(i) + 'a' - 'A');
	            else
	                output += new_id.charAt(i);
	        }
	        return output;
	    }
    
    private static String step2(String input){
        String output = "";
        for(int i = 0; i<input.length(); i++){
            if((input.charAt(i) >= 'a' && input.charAt(i) <= 'z') || 
               (input.charAt(i) >= '0' && input.charAt(i) <= '9') ||
              input.charAt(i) == '-' || input.charAt(i) == '_' || input.charAt(i) == '.')
                output += input.charAt(i);
            else
                continue;
        }
        return output;
    }
    
    private static String step3(String input){
        String output = "";
        boolean flag = false;
        for(int i = 0; i<input.length(); i++){
            if(input.charAt(i) == '.'){
                if(!flag){
                    output += input.charAt(i);
                    flag = true;
                }else
                    continue;
            }else{
                if(flag)
                    flag = false;
                output += input.charAt(i);
            }
        }
        return output;
    }
    
    private static String step4(String input){
        String output = "";
        for(int i = 0; i<input.length(); i++){
            if(i == 0 || i == input.length()-1){
                if(input.charAt(i) == '.')
                    continue;
            }
            output += input.charAt(i);
        }
        return output;
    }
    
    private static String step5(String input){
        if(input == "")
            return "a";
        return input;
    }
    
    private static String step6(String input){
        String output = "";
        if(input.length()>15){
            for(int i = 0; i<15; i++){
                if(i == 14 && input.charAt(i) == '.')
                    break;
                output += input.charAt(i);
            }
            return output;
        }
        return input;
    }
    
    private static String step7(String input){
        String output = "";
        if(input.length() <=2){
            int len = input.length();
            output = input;
            while(len!=3){
                output += input.charAt(input.length()-1);
                len++;
            }
            return output;
        }
        return input;
    }
}

- 대문자를 소문자로 바꾸는 toLowerCase() 함수도 있지만 라이브러리 사용없이 코딩. 

- 대문자를 소문자로 바꿀 때 32를 더하고 소문자를 대문자로 바꿀 때 32를 빼면 되지만, 32를 외울 필요 없이 'a' - 'A'(아스키 코드상 소문자값이 대문자보다 큼) 연산을 이용하면됨.

- step1에서 대문자를 소문자로 변환할 때 char 캐스팅을 하지 않으면 숫자값이 붙혀짐으로 char 캐스팅 해야함.

- step5에서 길이가 16이상일 때만 체크하는 조건을 수도코드에서 빼먹어서 오류발생 -> 확인 후 수정

 

자바에서 제공하는 String 함수 라이브러리를 활용하면 좀더 효율적인 코딩이 가능하지만 시험시 해당 코드들이 떠오르지 않거나 어떻게 활용해야할지 모르는 경우를 생각해 최대한 raw하게 코딩했다. 추후에 String 라이브러리를 최대한 활용하여 코드를 작성하는 연습도 필요함.