Coding Test/Programmers

[Lv.2] 기능개발 [프로그래머스_코딩테스트] [큐, 시뮬레이션] [35분]

whawoo 2025. 6. 20. 11:19
반응형

🔍 문제 요약

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

 

프로그래머스

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

programmers.co.kr

배포되어야 하는 순서에 따라서 현재까지 작업 진행도 progresses 배열이 정해져 있고 각 작업들의 속도가 Speeds에 적혀 있을 때 100프로가 되면 완료되어 배포된다 쳤을 때 각 배포마다 몇 개의 기능이 포함되어 배포되는지 결과 반환하는 문제

🧠 나의 접근 방식과 시행착오

30분에 푼 문제. 문제가 조금 독해하는데 난해하다고 느꼈던 문제. 결국은 prgress가 100이 되는데 필요한 날짜 (speed가 하루 단위로 본다)를 구하고 list를 순회하면서 이전 Day가 더 작은 수이면 다음 프로그레스 작업들은 하나의 묶음이 되고, 이전 Day보다 더 큰 수가 되면 새로운 묶음으로 판단되어서 계산시킨다. 문제가 progress와 speed를 묶은 건 괜찮게 생각했다고 봤는데 (사실 하나로 안 묶어도 상관은 없어 보임..) 그 뒤의 순회를 하면서 체크가 좀 지저분해진 느낌이 든다. 정리를 하면 정리가 될 거 같긴 함

using System;
using System.Collections.Generic;

public class Solution
{
    /// <summary>
    /// 기능개발
    /// https://school.programmers.co.kr/learn/courses/30/lessons/42586
    /// </summary>
    public int[] solution(int[] progresses, int[] speeds)
    {
        // progresses의 작업은 순차적으로 완료가 되어야 한다.
        // 속도도 중요하므로 일단 하나의 묶음으로 묶기
        List<(int, int)> list = new List<(int, int)>(progresses.Length);
        
        for (int i = 0; i < progresses.Length; i++)
        {
            list.Add((progresses[i], speeds[i]));
        }

        List<int> needDayList = new List<int>();

        for (int i = 0; i < list.Count; i++)
        {
            int needProg = 100 - list[i].Item1;
            int speed = list[i].Item2;

            int needDay = (int)Math.Ceiling(needProg / (double)speed);
            needDayList.Add(needDay);
        }

        // 인덱스 낮은 것부터 돌면서 필요한 날짜를 저장
        int beforeNeedDay = 0;
        int count = 0;
        List<int> answerList =  new List<int>();

        for (int i = 0; i < needDayList.Count; i++)
        {
            if (beforeNeedDay < needDayList[i])
            {
                beforeNeedDay = needDayList[i];

                if (count >= 1)
                {
                    answerList.Add(count);
                }

                count = 1;
            }
            else
            {
                count++;
            }

            if (i == needDayList.Count - 1 && count >= 1)
            {
                answerList.Add(count);
            }
        }
        
        return answerList.ToArray();
    }
}

/// <summary>
/// C# 7.3
/// </summary>
internal class Program
{
    public static void Main(string[] args)
    {
        var sl = new Solution();
        var progress1 = new int[] { 93, 30, 55 };
        var speeds1 = new int[] { 1, 30, 5 };
        var res1 = sl.solution(progress1, speeds1);
        var progress2 = new int[] { 95, 90, 99, 99, 80, 99 };
        var speeds2 = new int[] { 1, 1, 1, 1, 1, 1 };
        var res2 = sl.solution(progress2, speeds2);

        foreach (var i in res1)
        {
            Console.Write(i + ", ");
        }
        
        Console.WriteLine();
        
        foreach (var i in res2)
        {
            Console.Write(i + ", ");
        }
    }
}

✅ 풀이 코드

위에 적은대로 피드백에서 튜플로 굳이 묶은 부분을 제거되어 있다. (속도와 프로그레스가 동일 인덱스로 진행 가능) 추가로 0번 인덱스의 MayDay를 먼저 저장해두고 다음 인덱스부터 순차적으로 순회를 하면서 MaxDay 이하이면 count를 증가시키고 더 큰 경우 새로운 묶음으로 빠져나오게 처리되어있다. 필자의 경우 후처리로 예외처리가 늘어진 부분을 처음에 1개는 미리 넣고 한다는 생각으로 피드백이 되어있다. 그러고 마지막에 add를 한 번 더해주면서 마무리. 

public int[] solution(int[] progresses, int[] speeds)
{
    List<int> needDays = new List<int>();
    for (int i = 0; i < progresses.Length; i++)
    {
        int remain = 100 - progresses[i];
        int day = (int)Math.Ceiling(remain / (double)speeds[i]);
        needDays.Add(day);
    }

    List<int> answer = new List<int>();
    int currentMaxDay = needDays[0];
    int count = 1;

    for (int i = 1; i < needDays.Count; i++)
    {
        if (needDays[i] <= currentMaxDay)
        {
            count++;
        }
        else
        {
            answer.Add(count);
            currentMaxDay = needDays[i];
            count = 1;
        }
    }

    answer.Add(count);
    return answer.ToArray();
}

🔄 정리

어려운 로직은 아니나 괜히 자료구조에 집착하면서 튜플을 선언하고 집어넣는 실수를 주의하자. 로직의 핵심의 연산이 뒤에 뒤에 체크하고 다음 번에 더해지는 이런 케이스는 미리 초기 데이터를 세팅하고 시작하는 것이 깔끔한 해결책이 될 수 있다는 점도 기억하자.

반응형