🧬알고리즘/Programmers

[JavaScript] 모의고사

뉴발자 2024. 8. 23.
728x90

 

 

 

 

 

 

 

 

 

 

 

 

 

 

[JavaScript] 모의고사

 

 

문제

수포자는 수학을 포기한 사람의 준말이다.

 

수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 한다.

수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍는다.

 

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

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때,

 

가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 반환하는 함수를 작성하라.

 

가장 높은 점수를 받은 사람이 여럿일 경우, 배열을 오름차순으로 정렬한다.

 

 

예시

answers return
[1, 2, 3, 4, 5] [1]
[1, 3, 2, 4, 2] [1, 2, 3]

 

 

나의 풀이

function solution(answers) {
  const spj1 = "12345".repeat(Math.ceil(answers.length / 5)).split("");
  const spj2 = "21232425".repeat(Math.ceil(answers.length / 8)).split("");
  const spj3 = "3311224455".repeat(Math.ceil(answers.length / 10)).split("");
  let cnt = [0, 0, 0];
    
  answers.map((v, i) => {
    if(v === +spj1[i]) cnt[0] += 1;
    if(v === +spj2[i]) cnt[1] += 1;
    if(v === +spj3[i]) cnt[2] += 1;
  });
    
  return cnt.map((v, i) => {
    if (v === Math.max(cnt[0], cnt[1], cnt[2])) {
      return i+1;
    }
  }).filter(v => v);
}

 

 

다른 풀이

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;
}

 

 

풀이 방법

나의 풀이 방법

1. answers의 길이에 따라 "12345", "21232425", "3311224455" 문자열을 반복하는 문자열을 생성한 후 배열로 만든다.

const spj1 = "12345".repeat(Math.ceil(answers.length / 5)).split("");
const spj2 = "21232425".repeat(Math.ceil(answers.length / 8)).split("");
const spj3 = "3311224455".repeat(Math.ceil(answers.length / 10)).split("");

// 만약 answer의 길이가 12라면 12보다 긴 배열을 생성한다.
// spj1 = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
// spj2 = [2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5];
// spj3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

 

2. 정답 갯수를 담을 배열을 생성한 후 answers를 map() 함수로 반복해서

  answers의 value와 그 value의 index자리의 spj1[i], spj2[i], spj3[i]가 같다면 각각 cnt에 1을 더해준다.

let cnt = [0, 0, 0];
    
answers.map((v, i) => {
  if(v === +spj1[i]) cnt[0] += 1;
  if(v === +spj2[i]) cnt[1] += 1;
  if(v === +spj3[i]) cnt[2] += 1;
});

// 만약 answers의 값이 [1, 2, 3, 4, 5]일 때

// spj1 = [1, 2, 3, 4, 5]
// spj2 = [2, 1, 2, 3, 2, 4, 2, 5]
// spj3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]

// 1 === spj1[0], true이므로 cnt[0] += 1을 해준다.
// 1 === spj2[0], false이므로 아무것도 하지않는다.
// 1 === spj3[0], false이므로 아무것도 하지 않는다.

// cnt는 [1, 0, 0] 값을 가지게 된다.

 

3. 각 수포자의 정답 개수를 가진 cnt를 map() 함수를 사용해서 최대값을 구한 후 최대값과 일치하면 배열에 넣어준다.

 filter() 함수를 사용해서 null값이 아닌 값만 반환한다.

return cnt.map((v, i) => {
  if (v === Math.max(cnt[0], cnt[1], cnt[2])) {
    return i+1;
  }
}).filter(v => v);

// 1. Math.max(cnt[0], cnt[1], cnt[2]를 이용해서 최고 점수를 구한다.
// 2. 최고 점수와 같은 value의 경우 i+1을 리턴한다.
// 3. map에서 반환된 값이 [1, null, null]일 수도 있기때문에 filter()를 사용해서 null을 빼준다.

 

 

다른 풀이 방법

1. 수포자1, 수포자2, 수포자3의 반복되는 정답을 배열로 담아준다.

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];

 

2. filter() 함수를 사용해서 answers 배열의 값과 각 정답배열의 index의 값과 같을 때 반환해주고 그 값의 길이를 구한다.

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;

 

3. max값을 구한 후 각 길이와 max값을 비교해서 같다면 배열에 넣어준 후 반환한다.

var answer = [];

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

return answer;

 

확실히 나의 풀이보다 깔끔하고 직관적으로 파악하기 좋은 코드인 것 같다.

 

배열만 보면 무조건 map으로 엮으려는 생각을 버려야할 것 같다.

 

 

 

 

 

 

 

 

 

 

728x90

댓글