본문 바로가기
프로그래밍/알고리즘 문제풀이

[pg] 프로그래머스 기능개발

by 노잼인간이라불립니다 2023. 7. 19.

0. 개요

 다시~ 돌아온 코딩테스트~ 왠지 너무나 어려워~ .... 이렇게 노랫말 한 소절로 나의 마음을 이야기 하면서 시작해 볼까 한다. 부트캠프를 시작하고 그룹스터디의 메인 주제가 코딩테스트 준비로 잡힘으로 해서 (반) 강제적으로 코테준비를 시작했다. 그리고 각각의 문제를 풀면서 느꼈던 점을 남기고자 이 글을 작성한다.

 

1.  문제정의

 1. 프로그램 기능개발을 해야한다.

 2. 각 기능의 진도를 나타내는 배열이 주어진다. ex) [51,10,90]

 3. 각 기능 별로 진행할 수 있는 속도 배열이 주어진다 ex)[30, 20, 1]

 4. 프로그램은 각 순서대로 배포된다. (뒷 기능이 먼저 배포될 수 없다.)

 5. 첫 기능의 진도가 100, 두 번째 기능의 진도가 100이라면 같이 배포된다.

 

주어지는 것: 진도를 나타내는 배열, 진행할 수 있는 속도 배열.

구하고자 하는 것: 각 배포가 발생할 때 몇 개의 기능이 배포되는지 배열로 리턴.

 

 

2.  나의 사고 및 시도

 먼저 이 문제는 큐/스택 카테고리에 속해있던 문제였기 때문에 큐 아니면 스택을 사용해야 했다. 문제 내용을 보아하니 순서대로 진행되는 것에서 힌트를 얻어 큐로 진행하기로 마음먹었다.

 

 내가 생각한 로직은 이렇다.

1. function이라는 객체를 만들어 현재 진도와 속도를 필드로 저장.

2. 그렇게 만든 function들을 큐에 저장.

3. 큐에서 peek()해가면서 100이 될때까지의 day를 ++.

4. 100이되면 큐에서 poll() 하고, 다음 기능의 속도 x day를 곱해서 총 진도가 100이상이면 같이 배포, 아니면 3.의 과정을 반복.

5. 이렇게 되면 각 기능별 걸리는 day에 대한 배열이 생긴다.

6. 이 day 배열을 순회하면서 숫자 비교를하면서 같이 배포할 기능의 숫자를 정답으로 리턴할 배열에 저장.

 

3.  Code

/**
 * @author 
 * @since 2023-07-17
 *
 * 주제: 큐/스택
 * 문제: 기능개발
 * 접근방법: 큐를 이용해서 구현하면 좋겠다고 생각하고 시작.
 * 1. 일단 java에서 큐를 어떻게 구현해놓았는지 공부.
 * 2. progress와 speeds를 각각 큐로 만들고, 반복문을 돌리면서 큐의 각 앞부분을 검색하면서 계산결과가 100이 넘을 때까지의 day를 증가시키면서 100이 넘을시 day저장.
 * 3. 저장된 days의 날짜들을 보면서 count하여 리턴
 */
public class Solution {

    public static void main(String[] args) {
        int[] solution = solution(new int[]{93, 30, 55}, new int[]{1, 30, 5});
        Arrays.stream(solution).forEach(number -> System.out.println("number = " + number));
    }


    public static int[] solution(int[] progresses, int[] speeds) {
        // 현재 경과율
        Queue<Integer> progress = new LinkedList<>();
        // 일별로 추가할 경과율
        Queue<Integer> speed = new LinkedList<>();
        // 100이 넘는 날짜를 저장
        List<Integer> days = new ArrayList();

        // 배열을 큐로 변환
        Arrays.stream(progresses).boxed().forEach(number -> progress.offer(number));
        Arrays.stream(speeds).boxed().forEach(number -> speed.add(number));

        // 큐의 맨 앞부분을 검색하여 100이 넘을 때까지 day를 증가 시킴. 100이 넘으면 day를 저장하고, 해당 값들을 큐에서 제거.
        Integer day = 0;
        while (!progress.isEmpty()) {
            day++;
            if ( progress.peek() + (speed.peek() * day) >= 100) {
                days.add(day);
                day = 0;
                progress.poll();
                speed.poll();
            }
        }

        // days 안에 들어 있는 경과일들을 count해서 배열로 만들어 리턴
        return calculateProgressDayCount(days);
    }

    /**
     * days 안에 들어 있는 경과일들을 비교하여 count 해주는 메서드
     *
     * @param days 100이 되기까지의 필요한 날짜 리스트
     * @return
     */
    public static int[] calculateProgressDayCount(List<Integer> days){
        // 정답 count를 담을 List
        List<Integer> answer = new ArrayList<>();

        //days를 순회하면서 경과일의 count를 추출
        Integer compareNumber = days.get(0);
        Integer count = 0;
        for (int i = 0; i < days.size(); i++) {
            Integer targetNumber = days.get(i);
            if (compareNumber >= targetNumber) {
                count++;
            }else{
                answer.add(count);
                count=1;
                compareNumber = targetNumber;
            }
        }
        answer.add(count);
        return answer.stream().mapToInt(i -> i).toArray();
    }

4.  회고 및 깨달은 점

실제로 구현은 객체가 아닌 2개의 큐로 진행했지만 나머지 로직은 위에 로직과 동일하다. 오랜만에 문제를 풀어서 조금 어색하고, 어려운 느낌이었고, 인강으로 제공되는 자료구조/알고리즘 강의를 꼭 수강해야겠다고 다짐하게 되는 시간이었다.

 

 

참조

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