Algorithm/Unsolved

[Unsolved][C++] 프로그래머스 COS Pro 1급 카드셔플

랩실외톨이 2021. 8. 25. 06:45
반응형

https://programmers.co.kr/learn/courses/11114/lessons/70750

 

COS Pro 1급 C++ 모의고사 - 카드셔플

1부터 n까지 숫자가 적힌 카드 뭉치를 다음 규칙에 따라 카드 뭉치를 섞었을 때, 아래에서부터 k번째에 있는 카드에 적힌 숫자를 알아내려합니다. 카드 뭉치 가장 아래에는 1이 쓰여있으며, 위로

programmers.co.kr

 

 

1. 서론

 

이건 코딩이고 논리고 알고리즘이 문제가 아니라 그냥 수학 문제? 구현 문제? 그냥 나의 닫힌 사고에 어처구니가 없다.

 

2. 문제 풀이

 

1부터 n개의 카드를 섞는다. 그런데 규칙이 있다.

섞을 때 카드 뭉치 두 개를 절반으로 나눈 후 1이 포함되어 있는 카드 뭉치가 밑으로 가게 섞는 것이다.

말은 어렵게도 해놨지만 예시를 보면 그냥 반으로 나눈 후 1이 포함되어 있는 카드 뭉치 사이에 나머지 카드 뭉치의 숫자들을 하나씩 넣는 것이다.

그냥 내가 코드를 짰으면 어려운 문제가 아니었을 것이다. 그런데 이 문제는 내가 짜인 코드에서 딱 한 줄만 수정할 수 있다는 게 문제다.

처음에 코드를 눈으로 읽고 문제를 파악하는데 나는 처음에 생각 자체를 잘못해버렸다. 가정 자체를 아예 잘못했다.

 

처음에 카드 뭉치를 반으로 나누고 a배열에 반, b배열에 반을 넣게 해준다. 

그리고 그 a배열과 b배열을 적절히 불러내어 순서대로 card배열에 섞어서 입력하는 게 이 문제의 핵심이었다.

처음에 문제를 읽으니 a배열의 0, 1, 2번에 앞의 카드 뭉치인 1, 2, 3을 넣었다.

그리고 b배열에는 3, 4, 5번 배열에 나머지 4, 5, 6을 넣었다.

난 여기서 3, 4, 5번에 값을 넣는다는 것에 전혀 이상함을 느끼지 못했다. 그냥 그럴 수도 있지, 이 사람은 이렇게 짰나 보다. 

이렇게 생각하고 밑에 부분에 섞어서 넣는 부분을 수정해야겠다고 생각했다.

 

그런데 밑에서 갑자기 문제가 안 풀리기 시작했다.

위를 고치지 않는 경우

0, 2, 4 번째 값에 a배열의 0, 1, 2번이 i/2로 들어가는 것은 틀린 것이 아니다.

그런데 뒤의 b배열에서 3, 4, 5번에 값들이 들어가있는데 card 배열에 1, 3, 5번에 그 값들을 불러와야 하는 것이다.

만약 내가 짜는 문제였다면 그냥 변수 하나 선언해서 -1씩 해주면서 1, 3, 5를 맞췄겠지만 이 문제는 딱 한 줄만 고칠 수 있었다.

하지만 난 3, 4, 5번에 넣는게 문제라는 인식을 전혀 하지 못했기 때문에 변수를 선언하지 않고 3, 4, 5를 1, 3, 5로 만들기 위해 온갖 숫자 놀음을 다 해봤지만 결국 실패했고 30분이 지났다. 

 

이딴 문제에 30분이나 쓰고 있으니 포기해야겠다 생각하고 인터넷을 뒤져보니 3, 4, 5를 0, 1, 2로 바꾸는 게 답이었다.

0, 1, 2로 바꾸면 i/2해도 맞으니까... 머리가 띵하다.

다시 생각해도 처음으로 돌아간다면 이 문제를 틀릴 것 같아서. 그냥 발상 자체가 안 떠오를 것 같다.

이런 문제는 사실 많이 푼다고 느는 것도 아닌 것 같은데. (그리고 이런 문제는 많이 있지도 않다.)

사고력을 기르는 법 없을까...

 

3. 코드 설명

 

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int solution(int n, int mix, int k) {
    int answer = 0;
    
    vector<int> card(n);
    for(int i = 0; i < n; i++) 
        card[i] = i+1;
    
    while(mix--) {
        vector<int> card_a(n/2), card_b(n/2);
        
        for(int i = 0; i < n; i++) {
            if(i < n/2)
                card_a[i] = card[i];
            else
                card_b[i-n/2] = card[i]; // 여기가 포인트
        }
        
        for(int i = 0; i < n; i++) {
            if(i % 2 == 0)
                card[i] = card_a[i/2];
            else
                card[i] = card_b[i/2]; // 여기가 아니라
        }
    }
    
    answer = card[k-1];
    
    return answer;
}

// 아래는 테스트케이스 출력을 해보기 위한 main 함수입니다. 아래에는 잘못된 부분이 없으니 위의 코드만 수정하세요.
int main() {
    int n = 6;
    int mix = 3;
    int k = 3;
    int ret = solution(n, mix, k);
    
    // [실행] 버튼을 누르면 출력 값을 볼 수 있습니다.
    cout << "solution 함수의 반환 값은 " << ret << " 입니다." << endl;
}

 

카드 뭉치를 반으로 나눌 때 3, 4, 5에 값을 넣으면 1, 3, 5로 값을 가져오기 힘드니까...

아예 0,1,2에 넣고 i/2가 되게 하는 것이다....

정말 놀랍다... 내가 이렇게 코딩 머리가 없다는 사실이 ㅎ

 

 

 

 

반응형