본문 바로가기
ALGORITHM/프로그래머스 With JS

[프로그래머스] 모의고사 / Javascript

by LAY CODER 2021. 4. 28.

문제

 

코딩테스트 연습 - 모의고사

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다. 1번 수포자가 찍는

programmers.co.kr


 

TRY

let answers = [1, 3, 2, 4, 2, 1, 3, 2, 4, 2, 1, 3, 2, 4, 2, 1, 3, 2, 4, 2];

function solution(answers) {

    let answer = [];
    // supo : 수포자 찍는 방식
    let supo = [
        [1, 2, 3, 4, 5],
        [2, 1, 2, 3, 2, 4, 2, 5],
        [3, 3, 1, 1, 2, 2, 4, 4, 5, 5],
    ];

    // 수포자들의 점수를 넣을 배열
    let score = [];
    // 수포자 수 만큼 for문
    for (let i = 0; i < supo.length; i++) {
        // 정답 수 초기화
        let result = 0;

        // 시험문제 수 만큼 for문
        for (let j = 0; j < answers.length; j++) {
            // ex) [1,2,3,4,5] = 0~4번 인덱스의 값이 반복으로 들어가니
            // 5로 나눈 나머지 인덱스의 값을 계속 넣어주면 된다.
            supoAnswers = supo[i][j % supo[i].length];

            // 맞은 숫자를 구한다
            if (answers[j] === supoAnswers) {
                result++;
            }
        }
        // 맞은 숫자를 점수배열에 넣어준다.
        score.push(result);
    }

    // 맞은 점수가 최고점과 같을 경우 해당 인덱스를 answer 배열에 넣는다.
    for (let i = 0; i < score.length; i++) {
        if (score[i] === Math.max(...score)) {
            answer.push(i + 1);
        }
    }

    return answer;
}

console.log(solution(answers));

 

수포자가 찍는 방식을 배열로 만든 다음 수포자의 수 만큼 for문을 돌린다.

 

예를 들어, 찍는 방식이 [1,2,3,4,5] 이면 0~4번 인덱스의 값이 반복으로 들어가니

 

5로 나눈 나머지 인덱스의 값을 sudoAnswers에 넣고 정답과 비교하여 result 값을 구한다.

 

수포자들의 맞은 개수를 score 배열에 넣고 최고점과 같을 경우 answer에 넣고 answer를 return 한다.

 


 

Refactoring

let answers = [1, 3, 2, 4, 2, 1, 3, 2, 4, 2, 1, 3, 2, 4, 2, 1, 3, 2, 4, 2];

function solution(answers) {

    let answer = [];
    // supo : 수포자 찍는 방식
    let supo = [
        [1, 2, 3, 4, 5],
        [2, 1, 2, 3, 2, 4, 2, 5],
        [3, 3, 1, 1, 2, 2, 4, 4, 5, 5],
    ];

    let score = [];
    for (let i = 0; i < supo.length; i++) {
        // ex) answers = [1,3,2,4,2,1,3,2,4,2 ...] / supo[i] = [1,2,3,4,5,1,2,3,4,5 ...]
        // 각 인덱스의 값 비교해서 일치하는 값(정답)만을 가진 배열을 반환
        // 정답 수 : filter 된 배열의 길이
        score[i] = answers.filter(
            (element, index) => element === supo[i][index % supo[i].length],
        ).length;
    }

    let max = Math.max(...score);

    if (score[0] === max) answer.push(1);
    if (score[1] === max) answer.push(2);
    if (score[2] === max) answer.push(3);

    return answer;
}

console.log(solution(answers));

 

방식은 첫 번째와 비슷하지만 Array.filter()를 이용하여 수포자들의 맞은 개수를 보다 간편하게 구하였다.

 

정답 배열에서 해당 인덱스의 정답이 수포자의 정답과 같은 경우만 필터링하여

 

새로운 배열을 반환하고 그 배열의 길이를 구하면 정답의 갯수가 된다.

 

for문을 이용하지 않고 if문을 이용해서 최고점과 같은 경우

 

answer 배열에 push 해주는 걸 더 명시적으로 표현하였다. 

 


 

Best

let answers = [1, 3, 2, 4, 2, 1, 3, 2, 4, 2, 1, 3, 2, 4, 2, 1, 3, 2, 4, 2];

function solution(answers) {

   let answer = [];

    const man1 = [1, 2, 3, 4, 5];
    const man2 = [2, 1, 2, 3, 2, 4, 2, 5];
    const man3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

    let score = [0, 0, 0];

    for (let i = 0; i < answers.length; i++) {
        if (answers[i] === man1[i % man1.length]) score[0]++;
        if (answers[i] === man2[i % man2.length]) score[1]++;
        if (answers[i] === man3[i % man3.length]) score[2]++;
    }

    const max = Math.max(...score);

    for (let i = 0; i < score.length; i++) {
        if (max === score[i]) answer.push(i + 1);
    }

    return answer;
}

console.log(solution(answers));

 

filter 함수가 아무래도 메모리를 많이 잡아 먹기 때문에

 

score 배열을 0으로 초기화 하고 for문을 돌려 정답이 맞았을 때

 

1씩 증가시키는 방식이 보기에도 깔끔하고 메모리에서도 우위일 것 같다.

댓글