코딩테스트연습/프로그래머스

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

:)jun 2021. 12. 18. 17:52

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

 

코딩테스트 연습 - 기능개발

프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다. 또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는

programmers.co.kr

// 기능당 걸리는 기간을 같은 크기의 배열에다 넣어놓고 배열의 맨 처음 요소를 기준잡고 그것보다 큰 값이 나올때까지 cnt++
// 늘려주다가 큰 값이 나오면 그떄까지 한번에 배포. 그리고 그 다음것부터 기준 잡고 다시 cnt++ 해주기

// 테스트코드
package Quiz2;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class FunctionDevelopmentTest {

    FunctionDevelopment q;

    @BeforeEach
    void setUp() {
        q = new FunctionDevelopment();
    }

    @Test
    void test1() {
        assertArrayEquals(new int[]{2, 1}, q.solution(new int[]{93, 30, 55}, new int[]{1, 30, 5}));
    }

    @Test
    void test2() {
        assertArrayEquals(new int[]{1, 3, 2}, q.solution(new int[]{95, 90, 99, 99, 80, 99}, new int[]{1, 1, 1, 1, 1, 1}));
    }
}

//프로덕션코드

public class FunctionDevelopment {
    public int[] solution(int[] progresses, int[] speeds) {

        int[] daysToComplete = new int[progresses.length];

        for (int i = 0; i < progresses.length; i++) {
            daysToComplete[i] = (int) Math.ceil((100 - progresses[i]) / (double) speeds[i]);
        }

        StringBuffer stringBuffer = new StringBuffer();

        int pivotNumber = daysToComplete[0];
        int cnt = 0;

        for (int i = 0; i < daysToComplete.length; i++) {
            if (daysToComplete[i] <= pivotNumber) {
                cnt++;

                isLastElement(daysToComplete, stringBuffer, cnt, i);
                continue;
            }
            stringBuffer.append(cnt);
            stringBuffer.append(" ");
            pivotNumber = daysToComplete[i];
            cnt = 1;

            isLastElement(daysToComplete, stringBuffer, cnt, i);
        }


        String[] answer = stringBuffer.toString().split(" ");

        int[] answerToInt = new int[answer.length];

        for (int i = 0; i < answer.length; i++) {
            answerToInt[i] = Integer.parseInt(answer[i]);
        }
        return answerToInt;
    }

    private void isLastElement(int[] daysToComplete, StringBuffer stringBuffer, int cnt, int i) {
        if (i == daysToComplete.length - 1) {
            stringBuffer.append(cnt);
            stringBuffer.append(" ");
        }
    }
}
// 성공! 배열의 길이가 얼마나 나올지 몰라서 정답을 배열로 바로 받기는 좀 그렇고 StringBuffer로 받았다.
// 그리고 각 숫자마다 공백을 넣어서 나중에 split하기 편하도록 해줬다.
// 혹시 "  ".split("")하면 하나하나씩 쪼개지려나? 근데 그렇다 하더라고 한번에 배포하는 기능 갯수가
// 10개가 넘어가면 적용하기 힘들겠다. 그래도 한번 테스트!

import java.util.Arrays;

public class StringSplit {
    public static void main(String[] args) {
        String str = "1234";
        String[] arr = str.split("");
        System.out.println(Arrays.toString(arr));
    }
}

위 코드의 결과값

// 가능하네? 굿!
// 그래도 10개 이상 배포할때는 예외가 생기니까 여기에 적용시키면 안됨.
// StringBuffer말고 ArrayList사용해도 되겠다.
// ArrayList에서 바로 배열로 만들 수 있을까?

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ArrayListToArray {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }

        Integer[] listToArray = list.toArray(new Integer[0]);
        System.out.println(Arrays.toString(listToArray));
    }
}

위 코드의 결과값

// 가능!
// array -> ArrayList 로 바로 갈 수 있는 메소드가 있을까?

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ArrayToArrayList {
    public static void main(String[] args) {

        Integer[] arr = new Integer[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }

        List<Integer> list = new ArrayList(Arrays.asList(arr));
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i) + " ");
        }

    }
}

위 코드의 결과값

// Arrays.asList 사용해서 가능!

// 결론은 양쪽으로 가는 것이 둘다 가능하고 이 문제는 스트링버퍼에 넣어도 되지만 arraylist에 넣어도 깔끔하게 나왔겠다.
// 먼저 스트링버퍼로 풀었던 프로덕션코드 리팩토링하자!

// 프로덕션코드

public class FunctionDevelopment {
    public int[] solution(int[] progresses, int[] speeds) {

        int[] daysToComplete = new int[progresses.length];
        setDaysToComplete(progresses, speeds, daysToComplete);

        StringBuffer stringBuffer = new StringBuffer();
        int pivotNumber = daysToComplete[0];
        int cnt = 0;

        setAnswerByStringBuffer(daysToComplete, stringBuffer, pivotNumber, cnt);
        String[] answer = stringBuffer.toString().split(" ");

        int[] answerToInt = new int[answer.length];
        setAnswerToInt(answer, answerToInt);
        
        return answerToInt;
    }

    private void setAnswerToInt(String[] answer, int[] answerToInt) {
        for (int i = 0; i < answer.length; i++) {
            answerToInt[i] = Integer.parseInt(answer[i]);
        }
    }

    private void setAnswerByStringBuffer(int[] daysToComplete, StringBuffer stringBuffer, int pivotNumber, int cnt) {
        for (int i = 0; i < daysToComplete.length; i++) {
            if (daysToComplete[i] <= pivotNumber) {
                cnt++;

                isLastElement(daysToComplete, stringBuffer, cnt, i);
                continue;
            }
            stringBuffer.append(cnt);
            stringBuffer.append(" ");
            pivotNumber = daysToComplete[i];
            cnt = 1;

            isLastElement(daysToComplete, stringBuffer, cnt, i);
        }
    }

    private void setDaysToComplete(int[] progresses, int[] speeds, int[] daysToComplete) {
        for (int i = 0; i < progresses.length; i++) {
            daysToComplete[i] = (int) Math.ceil((100 - progresses[i]) / (double) speeds[i]);
        }
    }

    private void isLastElement(int[] daysToComplete, StringBuffer stringBuffer, int cnt, int i) {
        if (i == daysToComplete.length - 1) {
            stringBuffer.append(cnt);
            stringBuffer.append(" ");
        }
    }
}

// 성공! 이제 Arraylist에 넣어보자.

// 프로덕션코드 (ArrayList를 사용한 방법)

import java.util.ArrayList;
import java.util.List;

public class FunctionDevelopment_2 {
    public int[] solution(int[] progresses, int[] speeds) {

        int[] daysToComplete = new int[progresses.length];
        setDaysToComplete(progresses, speeds, daysToComplete);

        List<Integer> answerList = new ArrayList<>();
        int pivotNumber = daysToComplete[0];
        int count = 0;

        setAnswerList(daysToComplete, answerList, pivotNumber, count);

        Integer[] integerAnswer = answerList.toArray(new Integer[0]);

        int[] answer = new int[integerAnswer.length];
        setAnswer(integerAnswer, answer);
        
        return answer;
    }

    private void setAnswer(Integer[] integerAnswer, int[] answer) {
        for (int i = 0; i < integerAnswer.length; i++) {
            answer[i] = integerAnswer[i];
        }
    }

    private void setAnswerList(int[] daysToComplete, List answerList, int pivotNumber, int cnt) {
        for (int i = 0; i < daysToComplete.length; i++) {
            if (daysToComplete[i] <= pivotNumber) {
                cnt++;

                isLastElement(daysToComplete, answerList, cnt, i);
                continue;
            }
            answerList.add(cnt);
            pivotNumber = daysToComplete[i];
            cnt = 1;

            isLastElement(daysToComplete, answerList, cnt, i);
        }
    }

    private void setDaysToComplete(int[] progresses, int[] speeds, int[] daysToComplete) {
        for (int i = 0; i < progresses.length; i++) {
            daysToComplete[i] = (int) Math.ceil((100 - progresses[i]) / (double) speeds[i]);
        }
    }

    private void isLastElement(int[] daysToComplete, List answerList, int cnt, int i) {
        if (i == daysToComplete.length - 1) {
            answerList.add(cnt);
        }
    }
}

// 성공! 비교적 깔끔하네요!
// 그런데 다 해놓고 보니까 이 문제 주제가 "스택/큐" 네요..?
// 아? 갯수를 다 count로 다 셀 필요가 없이 값을 스택이나 큐에 다 넣어놨다가 들어있는 총 갯수만 출력해주면 되는거구나.
// 자료구조를 잘 활용하자!