• 티스토리 홈
  • 프로필사진
    유니얼
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
유니얼
  • 프로필사진
    유니얼
    • 분류 전체보기 (295)
      • Unity (17)
        • 게임 개발 (5)
      • Unreal (24)
        • 게임 개발 (20)
      • DirectX (36)
      • 코딩테스트 (91)
        • 프로그래머스 (25)
        • 백준 (66)
      • Google Workspace (1)
      • Programing (102)
        • C# (68)
        • C++ (24)
        • JavaScript (10)
      • 게임 서버 프로그래밍 (17)
      • Web (6)
        • 슈퍼코딩 (6)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
    등록된 댓글이 없습니다.
  • 최근 공지
    등록된 공지가 없습니다.
# Home
# 공지사항
#
# 태그
# 검색결과
# 방명록
  • [99클럽/코딩테스트 챌린지/C++] 모의고사 문제 풀이 및 리팩토링을 통한 가독성 향상과 코드 간소화
    2024년 11월 16일
    • 유니얼
    • 작성자
    • 2024.11.16.:06
    728x90

    문제 링크 : 

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

     

    프로그래머스

    SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

    programmers.co.kr

    문제 요약

    수포자 삼인방이 각각 일정한 규칙으로 답을 찍습니다. 문제의 정답 배열 answers가 주어질 때, 가장 많은 문제를 맞힌 사람(들)을 찾아서 오름차순으로 반환하는 문제입니다.

    접근법

    1. 각 수포자의 정답 규칙을 벡터로 정의합니다.
    2. 정답 배열을 순회하며 각 수포자가 정답을 맞힌 횟수를 기록합니다.
    3. 가장 높은 점수를 계산하고, 해당 점수를 얻은 수포자를 반환합니다.
    #include <algorithm>
    #include <iostream>
    #include <queue>
    #include <tuple>
    #include <vector>
    
    
    using namespace std;
    
    int number1(vector<int>& answers)
    {
    	int count = 0;
    	for(int i = 0; i < answers.size(); i++)
    	{
    		int ret = (i % 5) + 1;
    		if(ret == answers[i])
    		{
    			count++;
    		}
    	}
    	return count;
    }
    
    int number2(vector<int>& answers)
    {
    	int count = 0;
    	vector<int> tre = { 2, 1, 2, 3, 2, 4, 2, 5 };
    	for (int i = 0; i < answers.size(); i++)
    	{
    		int index = i % tre.size();
    		if (tre[index] == answers[i])
    			count++;
    	}
    	return count;
    }
    
    
    int number3(vector<int>& answers)
    {
    	int count = 0;
    	vector<int> tre = { 3,3,1,1,2,2,4,4,5,5 };
    
    	for (int i = 0; i < answers.size(); i++)
    	{
    		int index = i % tre.size();
    		if (tre[index] == answers[i])
    			count++;
    	}
    	return count;
    }
    
    
    vector<int> solution(vector<int> answers) {
        vector<int> answer;
        vector<pair<int, int>> pi;
        int max = 0;
        for(int i = 0; i < 3; i++)
        {
            int anw = 0;
            if (i == 0) anw = number1(answers);
            else if (i == 1) anw = number2(answers);
            else if (i == 2) anw = number3(answers);
    
            if(anw >= max)
            {
                if (pi.empty()) pi.push_back({ i + 1 ,anw});
                else
                {
                    if(pi[0].second < anw)
                    {
                        int count = pi.size();
                        for (int j = 0; j < count; j++)
                        {
                            pi.pop_back();
                        }
                        pi.push_back({ i + 1,anw });
                    }
                    else if(pi[0].second == anw)
                    {
                        pi.push_back({ i + 1 ,anw});
                    }
                }
                max = anw;
            }
        }
    
        for (auto a : pi)
        {
            answer.push_back(a.first);
        }
    
        sort(answer.begin(), answer.end());
    
        return answer;
    }

    기존 코드 문제점

    1. 중복된 코드:
      • number1, number2, number3 함수가 동일한 로직을 반복합니다.
      • 조건문(if (i == 0), else if)로 각 수포자 점수를 계산해 코드가 복잡합니다.
    2. 복잡한 데이터 관리:
      • vector<pair<int, int>> pi를 사용해 점수를 관리하며 불필요한 메모리 접근(pop_back)과 복잡한 비교 로직을 추가했습니다.
    3. 가독성 부족:
      • number1, number2, number3가 각각 별도의 함수로 정의되어 있어 코드 흐름을 따라가기가 어렵습니다.

    리팩토링 핵심

    1. 전역 벡터로 정답 패턴 관리: 각 수포자의 정답 패턴을 전역 vector로 정의하여 반복 코드 제거.
    2. 단일 루프로 점수 계산: 반복문 하나로 모든 수포자의 점수를 계산해 코드 가독성을 높임.
    3. STL 함수 활용: max_element를 사용해 가장 높은 점수를 직관적으로 계산.
    4. 데이터 구조 간소화: vector<int> 하나로 점수 관리, 복잡한 pair 구조 제거.
    #include <algorithm>
    #include <iostream>
    #include <queue>
    #include <tuple>
    #include <vector>
    
    using namespace std;
    
    vector<int> num1 = { 1,2,3,4,5 };
    vector<int> num2 = { 2, 1, 2, 3, 2, 4, 2, 5 };
    vector<int> num3 = { 3, 3, 1, 1, 2, 2, 4, 4, 5, 5 };
    
    vector<int> solution(vector<int> answers) {
        vector<int> answer;
    	vector<int> theys(3);
    
    	for(int i = 0; i < answers.size(); i++)
    	{
    		if (answers[i] == num1[i % num1.size()]) theys[0]++;
    		if (answers[i] == num2[i % num2.size()]) theys[1]++;
    		if (answers[i] == num3[i % num3.size()]) theys[2]++;
    	}
    
    	int maxValue = *max_element(theys.begin(), theys.end());
    	for(int i = 0; i < theys.size(); i++)
    	{
    		if(theys[i] == maxValue)
    		{
    			answer.push_back(i + 1);
    		}
    	}
        return answer;
    }

    리팩토링을 통해 배운 점

    1. 중복 제거의 중요성:
      • 반복적인 코드 구조는 데이터와 반복문으로 대체할 수 있다.
      • 동일한 작업을 하는 코드를 함수로 나누는 대신, 데이터 중심으로 간소화하는 것이 효과적이다.
    2. 가독성을 높이는 데이터 구조 설계:
      • 복잡한 자료구조보다 직관적인 자료구조(vector<int>)를 사용하는 것이 가독성과 유지보수 측면에서 유리하다.
    3. STL 함수 활용:
      • max_element와 같은 STL 함수를 적극 활용하면 코드가 간결하고 읽기 쉬워진다.

    느낀 점

    이번 리팩토링을 통해 "간단하고 직관적인 코드가 더 좋은 코드"라는 것을 배웠습니다. 처음 작성한 코드도 정답이었지만, 중복 코드와 복잡한 구조 때문에 유지보수가 어렵고 가독성이 낮았습니다. 리팩토링을 통해 코드가 단순해지고 문제 해결에 더 집중할 수 있었습니다. 앞으로도 코드를 작성할 때 가독성과 간결함을 항상 고려해야겠다고 느꼈습니다.

    반응형
    다음글
    다음 글이 없습니다.
    이전글
    이전 글이 없습니다.
    댓글
조회된 결과가 없습니다.
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
목차
표시할 목차가 없습니다.
    • 안녕하세요
    • 감사해요
    • 잘있어요

    티스토리툴바