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

하태현·2020년 11월 23일
0

알고리즘

목록 보기
2/4
post-thumbnail

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

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 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) {
  var answer = [];

  const rule1 = [1, 2, 3, 4, 5]; // length: 5
  const rule2 = [2, 1, 2, 3, 2, 4, 2, 5]; // length: 8
  const rule3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]; // length: 10

  function studentAnwser(rule) {
    let result = new Array(answers.length);
    for (let i = 0; i < result.length; i++) {
      if (i < rule.length) result[i] = rule[i];
      else result[i] = rule[i % rule.length];
    }
    return result;
  }
  const answerArray1 = studentAnwser(rule1);
  const answerArray2 = studentAnwser(rule2);
  const answerArray3 = studentAnwser(rule3);

  function answerCount(answerArray) {
    let count = 0;
    for (let i = 0; i < answers.length; i++) {
      if (answerArray[i] === answers[i]) count++;
    }
    return count;
  }

  const countArray = [
    answerCount(answerArray1),
    answerCount(answerArray2),
    answerCount(answerArray3),
  ];

  function getMaxOfArray(countArray) {
    return Math.max.apply(null, countArray);
  }

  countArray.forEach((count, studentNumber) => {
    if (count === getMaxOfArray(countArray)) answer.push(studentNumber + 1);
  });

  return answer.sort((a, b) => a - b);
}

solution([1, 2, 3, 4, 5]); // [ 1 ]
solution([1, 3, 2, 4, 2]); // [ 1, 2, 3 ]

우선 각 학생마다 번호를 찍는 규칙이 달라서 각 규칙마다 rule1 rule2 rule3 로 네이밍을 했다 .

학생마다 규칙대로 답을찍은 답안지를 만드는 용도로 studentAnwser(rule)로 만들었다.

여기서 중요한 것은 인자로 정답의 개수는 문제에서 주어진 대로 10000개 이하일 것이고,

학생들이 정답을 찍는 규칙이 (1번학생: 5개씩 반복, 2번학생: 8개씩 반복, 3번학생: 10개씩 반복) 각각 다르다.

그래서 인덱스 값에서 규칙배열 길이를 나눈 나머지(이 문제의 핵심이라고 생각한다.)를 이용해서 규칙을 반복할수 있도록 했다.

answerArray1,answerArray2,answerArray3 으로 각각의 답안지를 만들고

정답지와 학생들 답안지를 비교하는 함수로answerCount(answerArray) 작성

학생별 맞춘개수를 담는 배열중 최대값을 뽑아 학생 번호를 answer 배열에 넣어주고 오름차순 정렬하였다.

// # 코드 수정

function solution(answers) {
  var answer = [];

  const rule1 = [1, 2, 3, 4, 5];
  const rule2 = [2, 1, 2, 3, 2, 4, 2, 5];
  const rule3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

  function studentAnwser(rule) {
    return answers.filter((answer, i) => answer === rule[i % rule.length]);
  }

  const countArray = [
    studentAnwser(rule1).length,
    studentAnwser(rule2).length,
    studentAnwser(rule3).length,
  ];

  countArray.forEach((count, studentNumber) => {
    if (count === Math.max.apply(null, countArray)) answer.push(studentNumber + 1);
  });

  return answer.sort((a, b) => a - b);
}

solution([1, 2, 3, 4, 5]); // [ 1 ]
solution([1, 3, 2, 4, 2]); // [ 1, 2, 3 ]

코드를 다시 보면서 중복된 부분이나 필요없는 부분을 정리해 보았다.

우선 학생별 답안지를 따로 배열을 만들 필요가 없었다. 맞춘 개수를 찾는 문제이기에

인자로 받은 정답지를 순회하며, 학생별 규칙(1번학생: 5개씩 반복, 2번학생: 8개씩 반복, 3번학생: 10개씩 반복) 이 답안지라고 생각하고

filter() 메소드를 이용해서 정답을 비교하고 맞췄을 경우에만 해당 값을 새로운 배열에 담아준다.

그 배열의 length 가 학생별 맞춘 개수이다.


Array.prototype.filter()

주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.

arr.filter(callback(element[, index[, array]])[, thisArg])

매개변수

callback

  • 각 요소를 시험할 함수. true를 반한화면 요소를 유지하고, false 를 반환하면 버린다.
    • element : 현재 처리할 요소
    • index : 현재 처리할 요소의 인덱스
    • array : filter 를 호출한 배열.
  • thisArg : callback을 실행할 때 this로 사용하는 값.

반환 값

테스트를 통화한 요소로 이루어진 새로운 배열. 어떤 요소도 테스트를 통과하지 못했으면 빈 배열을 반환한다.

profile
왜?를 생각하며 개발하기, 다양한 프로젝트를 경험하는 것 또한 중요하지만 내가 사용하는 기술이 어떤 배경과 이유에서 만들어진 건지, 코드를 작성할 때에도 이게 최선의 방법인지를 끊임없이 질문하고 고민하자. 이 과정은 앞으로 개발자로 커리어를 쌓아 나갈 때 중요한 발판이 될 것이다.

0개의 댓글