알고리즘

[programmers] 모음사전

졔졔311 2023. 8. 27. 13:59
728x90
반응형

https://school.programmers.co.kr/learn/courses/30/lessons/84512

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

---------------------------------------------------핵심 알고리즘--------------------------------------------

 

완전탐색

 

---------------------------------------------------풀이----------------------------------------------------

 

사전 순서를 고려한다고 생각하지 말고, 숫자라고 생각하면 좋을 것 같다.

소숫점을 생각한다면, A = 0.1, AAA = 0.111, AAAU = 0.1115, ... 등 이다.

이 방식대로 A부터 시작해 완전탐색을 통해 몇 번째 문자열인지 구하는 방식이다.

 

알고리즘은 다음과 같다.

빈 문자열 ans를 준비한 뒤, 증가시키면서 이 문자열이 구하고자 하는 문자열에 해당하는 word와 일치하면 그 때의 answer를 리턴한다.

즉, ans를 사전 순서대로 하나씩 다음 문자열로 바꾸어 나가고,

그 때마다 answer를 1 증가시킨다.

만약 word와 일치하면 종료한다.

 

이를 위해 while문을 word와 ans가 같아질 때까지 반복하였다.

우선, ans 맨 뒤에 'A'를 추가한다. ( 소숫점에서 맨 뒤에 1이 붙는 것이 그 다음으로 작은 숫자가 되므로 - 즉, 0.23 다음은 0.231이다.)

그런데 ans의 가능한 최대 길이는 5이므로 그것보다 크면 반올림을 해준다.

예를 들어, AAAAE에서 A를 덧붙이면 AAAAEA가 된다.

그런데 길이가 5를 넘어가므로, 맨 뒤의 A를 삭제한 뒤 carry를 E의 위치에 더해주는 방식이다.

E 다음은 I이므로 AAAAEI가 된다.

이와같은 방식으로 맨 뒤 문자는 삭제하고, carry를 바로 위 자릿수에 더해 문자를 바꿔준다.

그런데, 제일 큰 문자인 U는 다음 문자가 없으므로 U에서 반올림 될 경우 다시 carry가 발생한다.

이 케이스는 결국, 다시 U가 위치했던 자릿수부터 carry를 올려주는 것이 반복되는 상황이다.

따라서 다른 문자들(A, E, I, O)의 경우, carry가 발생하면 그 다음 문자로 옮겨주기만 하면 되지만,(A->E->I->O->U)

U의 경우, 이 문자의 위치에서 다시 carry가 발생해 그 위로 carry를 올려줘야 한다.

예를 들면, AAAAU에서 A를 뒤에 추가해 AAAAUA가 되는데,

5자리 이상이므로 마지막 A를 삭제하고 AAAAU에서 U에 carry를 더해준다.

그런데 U 다음 문자는 없으므로 다시 이 과정을 반복한다.

따라서 AAAAU에서 맨 뒤의 U를 삭제하고, 마지막 A에 carry를 더해 AAAAU->AAAA->AAAE로 변경되는 것이다.

 

정리하면,

1. ans의 마지막에 A를 추가한다.

2. 길이가 5보다 크면 뒤에서부터 반올림한다.

2.1. 맨 뒤의 문자를 삭제한다.

2.2. A면 E, E면 I, E면 O, O면 U로 바꿔주고 종료한다.

2.3. U면 2.1부터 다시 반복한다.

이 과정을 ans가 word와 같아질 때까지 반복한다.

#include <string>
#include <vector>

using namespace std;

// A AA AAA AAAA AAAAA AAAAE AAAAI AAAAO AAAAU AAAE AAAEA 
int solution(string word) {
    int answer = 0;
    string ans = "";
    while(word != ans){
        // ans를 다음 단어로 옮김 => 뒤에서부터 확인
        // 1. 뒤에 A를 추가
        ans += 'A';
        // 2. 길이가 5보다 크면 뒤에서부터 반올림
        if(ans.length() > 5){
            int i = 5;
            while(i--){
                // 뒷부분 길이 넘는 문자 제거
                ans.erase(ans.begin() + i+1);
                if(ans[i] == 'A'){
                    ans[i] = 'E';
                }
                else if(ans[i] == 'E'){
                    ans[i] = 'I';
                }
                else if(ans[i] == 'I'){
                    ans[i] = 'O';
                }
                else if(ans[i] == 'O'){
                    ans[i] = 'U';
                }
                // 반올림 후 위로 carry가 생기는 경우
                else if(ans[i] == 'U'){
                    // 다음 문자에 대해 한 번 더 해야함.
                    continue;
                }
                // carry가 없을 경우 종료.
                break;
            }
        }
        answer++;
    }
    return answer;
}

 

---------------------------------------------------후기----------------------------------------------------

 

완전탐색 문제라고 생각하면 매우 간단했던 문제이다.

728x90
반응형

'알고리즘' 카테고리의 다른 글

[programmers] 길 찾기 게임  (0) 2024.03.09
[programmers] 양과 늑대  (0) 2024.03.04
[programmers] 빛의 경로 사이클  (0) 2023.08.26
[programmers] 전력망을 둘로 나누기  (0) 2023.06.22
[programmers] 교점에 별 만들기  (1) 2023.06.17