본문 바로가기
프로그래머스

24/08/12 - 카드 뭉치, 과일 장수, 모의고사(C++, JS)

by Jini_Lamp 2024. 8. 12.

1. 카드 뭉치(https://school.programmers.co.kr/learn/courses/30/lessons/159994?language=c)

 

카드 뭉치 두 개가 주어졌을 때, 각 카드 뭉치 순서대로 나열되어 있는 영어 단어를 토대로 영어 문장을 만들 수 있는지 없는지 판단하는 문제다. 이때 영어 문장의 길이는 두 카드 뭉치의 합보다 클 수 없다.

예를 들어 아래와 같은 예제가 있을 때, 내가 사용한 방법은 다음과 같다.

  • cards1: ["i", "drink", "water"]
  • cards2: ["want", "to"]
  • goal: [ "i", "want", "to" , "drink", "water" ]

 

먼저 영어 문장 goal의 크기 만큼 반복문을 돌린다. 예제를 참고하면 총 5번 반복문이 돌아간다.

그리고 반복문 순서에 맞게 cards1, cards2와 gola의 단어를 비교한다. 만약 현재 비교하는 i번째에서, cards1에 있는 단어가 goal의 단어와 일치하지 않으면 다시 cards2와 goal를 비교한다. cards2에도 일치하지 않으면 해당 단어가 카드 뭉치에 없거나 카드 뭉치의 순서가 이상한 것이므로 "No"를 리턴한다. card_len1과 card_len2는 cards1, cards2의 다음 단어를 비교하기 위해 필요한 것으로, goal의 크기보다 클 수는 없다.

정리하면 다음과 같다.

  1. goal의 크기 만큼 반복문을 돌린다
  2. cards1, cards2의 단어와 gola의 단어를 비교한다.
  3. 일치하면 card_len1이나 card_len2의 크기를 1씩 늘린다.
  4. 일치하지 않으면 No를 반환한다.
// c++
#include <string>
#include <vector>

using namespace std;

string solution(vector<string> cards1, vector<string> cards2, vector<string> goal) {
    int card_len1 = 0;
    int card_len2 = 0;
    
    for(int i=0; i<goal.size(); i++)
    {
        if(card_len1 < cards1.size() && goal[i] == cards1[card_len1])
            card_len1++;
        else if(card_len2 < cards2.size() && goal[i] == cards2[card_len2])
            card_len2++;
        else
            return "No";
    }
    
    return "Yes";
}

 

아래는 JS이다. 푸는 방법은 c++과 같다.

function solution(cards1, cards2, goal) {
    var card_len1 = 0;
    var card_len2 = 0;
    
    for(var i=0; i<goal.length; i++)
    {
        if(card_len1 < cards1.length && goal[i] == cards1[card_len1])
            card_len1++;
        else if(card_len2 < cards2.length && goal[i] == cards2[card_len2])
            card_len2++;
        else
            return "No";
    }
    
    return "Yes";
}

 

 

 

2. 과일 장수(https://school.programmers.co.kr/learn/courses/30/lessons/135808)

 

과일을 m개로 나누고, 해당 묶음에서 가장 작은 과일 * m 를 계산하여 총 얼마가 나오는지 계산하는 문제이다.

문제 풀이는 다음과 같다.

  1. 전체 과일을 내림차순으로 정렬한다.
  2. 전체 과일 수 만큼 반복문을 돌린다.
  3. nCount가 나눠야 하는 과일 개수(m)과 같아지면,
  4. 현재 과일 점수 * m을 해서, answer에 더한다.
// c++
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int solution(int k, int m, vector<int> score) {
    int answer = 0;
    int nCount = 1;
    
    sort(score.rbegin(), score.rend());
    
    for(int i=0; i<score.size(); i++, nCount++)
    {
        if(nCount == m)
        {
            nCount = 0;	// 0을 해주는 이유는, 반복문이 끝나면 +1이 되기 때문이다.
            answer += m * score[i];
        }
    }
    
    return answer;
}

 

이렇게 문제를 푼 이유는 최대 점수를 내기 위해 먼저 가장 큰 순서대로 m개를 만들 것이고, 그중 가장 작은 숫자 * m을 할 것이기 때문이다.

 

따라서 JS도 문제 푸는 방식은 동일하다.

// js
function solution(k, m, score) {
    var answer = 0;
    var nCount = 1;
    
    score.sort(function(a, b)  {
      return b - a;
    });
    
    for(var i=0; i<score.length; i++, nCount++)
    {
        if(nCount == m)
        {
            nCount = 0;
            answer += m * score[i];
        }
    }
    
    return answer;
}

 

 

 

3. 모의고사(https://school.programmers.co.kr/learn/courses/30/lessons/42840)

 

특정 패턴으로 문제를 찍는 학생 3명이 있다. 그중 가장 많은 문제를 맞힌 학생이 누구인지 알아내는 문제이다.

 

먼저 학생 1, 2, 3이 각각 몇 문제를 맞혔는지 알기 위해 반복문을 돌린다.

    for(int i=0; i<answers.size(); i++)
    {	// 학생1, 2, 3이 몇 문제를 맞혔는지 센다.
        if(answers[i] == man1[i % len1])
            count[0]++;
        if(answers[i] == man2[i % len2])
            count[1]++;
        if(answers[i] == man3[i % len3])
            count[2]++;
    }

 

그런 다음 학생 수만큼 반복문을 돌리는데, 맨 처음 학생은 일단 집어 넣는다.

이후 첫번째 학생과 두번째 학생을 비교하게 되는데, 두번째 학생이 맞힌 수가 첫번째 학생이 맞힌 수보다 많으면(count[i - 1] < count[i]) 기존에 집어 넣었던 첫번째 학생은 제거하고 두번째 학생을 집어 넣는다.

 

그리고 두번째 학생보다 첫번재 학생이 더 맞힌 경우, 두번째 학생이 맞힌 문제의 개수를 첫번째 학생이 맞힌 개수로 바꾼다. 왜냐하면 이렇게 해야 첫번째와 세번째를 비교할 수 있기 때문이다.

    for(int i=0; i<3; i++)
    {	// 현재 맞힌 개수가 이전에 맞힌 개수보다 크다면,
    	// 이전에 삽입된 맞힌 개수의 학생을 벡터에서 제거한다.
        if(i != 0 && count[i - 1] < count[i])
        {
            answer.pop_back();
        }
        else if(i != 0 && count[i] < count[i - 1])
        {// 이전에 맞힌 개수가 현재 맞힌 개수보다 크다면
        // 현재 맞힌 개수를 이전에 맞힌 개수로 변경한 뒤
            // 삽입을 방지하기 위해 그대로 건너뛴다.
            count[i] = count[i - 1];
            continue;            
        }
        // 학생을 집어 넣는다.
        answer.push_back(i + 1);
    }

 

아래는 최종 코드이다.

#include <string>
#include <vector>

using namespace std;

vector<int> solution(vector<int> answers) {
    vector<int> answer;
    int man1[] = {1, 2, 3, 4, 5};
    int man2[] = {2, 1, 2, 3, 2, 4, 2, 5};
    int man3[] = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
    int len1 = sizeof(man1)/sizeof(*man1), count[] = {0, 0, 0};
    int len2 = sizeof(man2)/sizeof(*man2);
    int len3 = sizeof(man3)/sizeof(*man3);
    
    for(int i=0; i<answers.size(); i++)
    {	// 학생1, 2, 3이 몇 문제를 맞혔는지 센다.
        if(answers[i] == man1[i % len1])
            count[0]++;
        if(answers[i] == man2[i % len2])
            count[1]++;
        if(answers[i] == man3[i % len3])
            count[2]++;
    }
    
    for(int i=0; i<3; i++)
    {	// 현재 맞힌 개수가 이전에 맞힌 개수보다 크다면,
    	// 이전에 삽입된 맞힌 개수의 학생을 벡터에서 제거한다.
        if(i != 0 && count[i - 1] < count[i])
        {
            answer.pop_back();
        }
        else if(i != 0 && count[i] < count[i - 1])
        {// 이전에 맞힌 개수가 현재 맞힌 개수보다 크다면
        // 현재 맞힌 개수를 이전에 맞힌 개수로 변경한 뒤
            // 삽입을 방지하기 위해 그대로 건너뛴다.
            count[i] = count[i - 1];
            continue;            
        }
        // 학생을 집어 넣는다.
        answer.push_back(i + 1);
    }
    
    return answer;
}

 

하지만 코드를 보았을 때, 어딘가 복잡해 보인다.

그래서 아래와 같이 변경하여 코드를 풀었다.

#include <string>
#include <vector>

using namespace std;

vector<int> solution(vector<int> answers) {
    vector<int> answer;
    int man1[] = {1, 2, 3, 4, 5};
    int man2[] = {2, 1, 2, 3, 2, 4, 2, 5};
    int man3[] = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
    int len1 = sizeof(man1)/sizeof(*man1), count[] = {0, 0, 0};
    int len2 = sizeof(man2)/sizeof(*man2);
    int len3 = sizeof(man3)/sizeof(*man3);
    
    for(int i=0; i<answers.size(); i++)
    {	// 학생1, 2, 3이 몇 문제를 맞혔는지 센다.
        if(answers[i] == man1[i % len1])
            count[0]++;
        if(answers[i] == man2[i % len2])
            count[1]++;
        if(answers[i] == man3[i % len3])
            count[2]++;
    }
    
    int max = count[0];
    for(int i=1; i<3; i++)
    {	// 가장 많이 맞힌 게 몇 문제인지 본다.
        if(max < count[i])
            max = count[i];
    }
    
    for(int i=0; i<3; i++)
    {	// 가장 많이 맞힌 개수와 일치하는 학생을 집어 넣는다.
        if(max == count[i])
            answer.push_back(i + 1);
    }
    
    return answer;
}

 

아래는 JS 풀이 과정이다.

function solution(answers) {
    var answer = [];
    var man1 = [1, 2, 3, 4, 5];
    var man2 = [2, 1, 2, 3, 2, 4, 2, 5];
    var man3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];
    var len1 = man1.length, count = [0, 0, 0];
    var len2 = man2.length;
    var len3 = man3.length;
    
    for(var i=0; i<answers.length; i++)
    {
        if(answers[i] == man1[i % len1])
            count[0]++;
        if(answers[i] == man2[i % len2])
            count[1]++;
        if(answers[i] == man3[i % len3])
            count[2]++;
    }
    
    var max = count[0];
    for(var i=1; i<3; i++)
    {
        if(max < count[i])
            max = count[i];
    }
    
    for(var i=0; i<3; i++)
    {
        if(max == count[i])
            answer.push(i + 1);
    }
    
    return answer;
}