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

Changyun Go·2021년 8월 10일
0
post-thumbnail

모의고사

문제 설명


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

1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한 사항


  • 시험은 최대 10,000 문제로 구성되어있습니다.
  • 문제의 정답은 1, 2, 3, 4, 5중 하나입니다.
  • 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.

나의 풀이


function solution(answers) {
    const students = [[1, 2, 3, 4, 5],[2, 1, 2, 3, 2, 4, 2, 5],[3, 3, 1, 1, 2, 2, 4, 4, 5, 5]];
    let student = [];
    const result = [];
    const answer = [];
    let correct = 0;
    let count = 0;
    
    for(let x = 0; x < students.length; x++){
        student = students[x];
        if(answers.length > student.length){
            for(let y = 0; y < Math.floor(answers.length / student.length); y++){
                for(let i = 0; i < student.length; i++){
                    student[i] === answers[count] ? correct++ : null;
                    count++;
                }
            }
            for(let z = 0; z < answers.length % student.length; z++){
                    student[z] === answers[count] ? correct++ : null;
                    count++;
            }
        }
        else{
            for(let i = 0; i < student.length; i++){
                student[i] === answers[count] ? correct++ : null;
                count++;
            }
        }
        result[x] = correct;
        count = 0;
        correct = 0;
    }
    
    let max = result.reduce((a,b) => a > b ? a : b);
    
    let idx = result.indexOf(max);
    while (idx !== -1) {
        answer.push(idx + 1);
        idx = result.indexOf(max, idx + 1);
    }
    
    return answer;
}
}

다른 사람의 풀이


function solution(answers) {
    var answer = [];
    var a1 = [1, 2, 3, 4, 5];
    var a2 = [2, 1, 2, 3, 2, 4, 2, 5]
    var a3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

    var a1c = answers.filter((a,i)=> a === a1[i%a1.length]).length;
    var a2c = answers.filter((a,i)=> a === a2[i%a2.length]).length;
    var a3c = answers.filter((a,i)=> a === a3[i%a3.length]).length;
    var max = Math.max(a1c,a2c,a3c);

    if (a1c === max) {answer.push(1)};
    if (a2c === max) {answer.push(2)};
    if (a3c === max) {answer.push(3)};


    return answer;
}

P.S.

이번 문제는 완전 억지로 풀었다 해도 과언이 아니다😫 시작과 끝이 있는 반복이 아닌 데다가, 배열 중간에서 멈출 수도 있는 반복이라니..😵 마지못해 for 문과 if 문을 조합해서 정답의 길이를 찍는 규칙의 길이로 나누어서 몫과 나머지를 따로 반복하는 삽질을 했다. 심지어 제대로 값이 나오려면 추가적인 조건들까지 고려해 줘야 하는 불편한 코드를 짜면서 화가 났지만 그래도 스스로의 힘으로 해봐야 한다는 생각으로 문제를 풀 수 있었다😂 다른 사람이 짠 코드를 보고 허탈한 마음도 들었지만, 그만큼 내공의 중요성을 느꼈고 비효율적인 코드를 짤 때의 문제점을 온몸으로 체감할 수 있었다.

내가 코드를 짜면서 사용했던 reduce 메소드와 다른 사람의 풀이에서 사용된 filter 메소드를 이해하려면 몇 가지의 선행적인 지식이 필요했다. TIL을 통해 정리해서 복습하는 기회를 가져야겠다.

다른 사람의 풀이를 보면, 수포자 3명의 찍는 규칙을 각각의 배열로 정의하고, filter 메소드를 통해 answers와 수포자들의 찍기 배열을 비교해서 일치하는 요소만 새로운 배열로 반환하고, 배열 길이의 최댓값을 구해서 n번 수포자의 정답 수가 최대일 경우 answer에 n을 요소로 반환하는 방식으로 문제를 풀었다.

filter에 들어간 인자들을 살펴보면 a === a1[i%a1.length]에서 a는 answers 의 배열 내의 값을 의미하고, i는 answers의 인덱스를 의미한다. 따라서 a1[i%a1.length]는 answers의 인덱스를 a1의 길이로 나눈 나머지들이 a1 배열에서 주기에 따라 인덱스를 계속 순회하도록 만든 코드이다.

나머지들이 주기에 따라 순회하는 원리는 다음과 같다. i%a1.length는 0에서 5를 나눈 나머지 값 0을 의미한다. 1%5=1, 2%5=2, 3%5=3, 4%5=4, 5%5=0, 6%5=1... 이런 식으로 0부터 4까지 반복시킬 수 있다.

0개의 댓글