1번 문제

김철준·2022년 1월 9일
0

코딩테스트

목록 보기
2/2

모의고사

본 문제는 프로그래머스의 LEVEL1문제이다.
해당문제링크 : 모의고사
문제내용은 다음과 같다.

문제의 이해와 코드 구현

이러한 코딩테스트 연습이 처음인지라 문제를 이해하는데에도 시간이 걸렸고 문제를 코드로 어떻게 구현해야될지가 감이 잡히지 않았다.

해결하기이에 앞서 다음과 같은 의문과 문제가 있었다.

  1. 수포자1,2,3이 있는데 이들을 숫자 1,2,3으로 표현하여 answer에 담아야하는데 수포자들을 숫자(1,2,3)으로 표현할 수 있는 방법은 무엇이 있을까?

  2. 시험이 최대 10,000 문제라는 것은 코드로 구현해야하는 부분인 것인지, 아니면 코드의 효율성을 고려하여 문제에 대하여 코드를 구현해야된다는 것인지 의도 파악을 잘 못했다는 점

  3. 가장 많이 맞춘 사람이 중복된다면 오름차순(1,2,3)으로 정렬해줄 수 있는 방법은 무엇일까?

  4. 가장 많이 맞춘 사람의 답을 정답과 비교할 수 있는 방법은 무엇일까?

코드 참조

계속 머리를 싸매고 있기보단 다른 사람들의 코드를 보는게 낫다는 생각이 들어 여러가지 풀이방법을 찾아보았다.

역시 풀이방법을 보아도 코드를 보고 이해하는데 한참이 시간이 걸렸고
나같은 입문자는 이러한 코드를 구현할 수 있다는게 대단하다는 생각이 들었다.

이러한 알고리즘을 아직 구현할 수 있는 단계가 아니라는 생각이 들어 문제에 대한 여러 사람들의 코드를 참조해보며 익혀보겠다.

첫번째 풀이

코드를 보며 하나씩 분석해보겠다.
코드는 가독성을 위하여 내가 조금만 변경해보았다.

function solution(answers) {
  let answer = [];
  const person1 = [1, 2, 3, 4, 5];
  const person2 = [2, 1, 2, 3, 2, 4, 2, 5];
  const person3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

  let point = [0, 0, 0];
  for (let i = 0; i < answers.length; i++) {
    if (answers[i] === person1[i % 5]) point[0]++;
    if (answers[i] === person2[i % 8]) point[1]++;
    if (answers[i] === person3[i % 10]) point[2]++;
  }
  let max = 0;
  for (let j = 0; j < point.length; j++) {
    if (point[j] > max) max = point[j];
  }

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

패턴

  const person1 = [1, 2, 3, 4, 5];
  const person2 = [2, 1, 2, 3, 2, 4, 2, 5];
  const person3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

우선 수포자1,수포자2,수포자3의 정답패턴을 분석하여
person1 , person2 , person3에 담아주었다.

수포자1은 1,2,3,4,5의 패턴을 반복하여 찍었다.
수포자2는 2,1,2,3,2,4,2,5라는 패턴을 반복하여 찍었다.
수포자3은 3, 3, 1, 1, 2, 2, 4, 4, 5, 5라는 패턴을 반복하여 찍었다.

point(맞춘 정답 수)

  let point = [0, 0, 0];

point라는 배열은 person1, person2, person3가 맞춘 정답 수를 담기 위한 배열이고 순서대로 정답이 담길 예정이다.

정답(point) 담기

  for (let i = 0; i < answers.length; i++) {
    if (answers[i] === person1[i % 5]) point[0]++;
    if (answers[i] === person2[i % 8]) point[1]++;
    if (answers[i] === person3[i % 10]) point[2]++;
  }

answers : 정답

answers는 정답이 담긴 배열이며 매개변수이다. 즉, 문제가 몇 개인지 명시되있지 않으므로 문제 갯수(answers.length) 기준으로 for문을 순회한다.

for문으로 정답이 담긴 배열과 수포자들 답을 첫요소부터 하나씩 비교하는데 이 때 주목해야 할 부분은 이 부분이다.

person1[i % 5] // i % 정답 패턴
person2[i % 8]
person3[i % 10]

각 수포자의 인덱스 : i % 정답 패턴

수포자의 인덱스를 i를 정답 패턴으로 나눴을 때 나머지 값을 인덱스로 주었다.

이 때 이런 코드가 아닌 이러한 코드로 짠다면 어떻게 될까?

person1[i] 
person2[i]
person3[i]

문제 수(answers)가 많아진다면 수포자들의 답과 비교할 수 없어지게 된다.
위 person1,2,3은 수포자들의 모든 답이 아닌 패턴을 지정해준 것이다.
때문에 문제가 많아진다면 person의 요소를 순회할 수 있는 범위를 초과하게 된다.

그래서 패턴만 가지고 문제를 순회할 수 있도록 나머지 값을 활용한 것이다.
person1의 패턴 같은 경우는 5번 주기로 반복된다.
5번이 넘어가 6번이 됬을 때는 다시 첫번째 요소로 넘어갈 수 있도록 해야한다.
그렇게 하기 위해서 i % 5라는 코드를 구현한 것이다.
이렇게 코드를 구현한다면 person1은 5개의 요소밖에 없는 배열이지만
answers(문제)가 많아도 패턴대로 순회할 수 있게 된다.

point[0]++
point[1]++
point[2]++

그리하여 정답과 수포자들의 답을 비교하여 맞춘 정답 수를 차례대로 담아줄 수 있다.

max (제일 정답을 많이 맞춘 사람의 정답수)

다음 코드를 살펴보자.

let max = 0;
  for (let j = 0; j < point.length; j++) {
    if (point[j] > max) max = point[j];
  }

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

여기서 max는 무엇을 의미할까?
제일 정답을 많이 맞춘 사람의 정답수를 의미한다.

max => 제일 정답을 많이 맞춘 사람의 정답수

for 문으로 point.length(수포자들 수)만큼 순회하여
각 수포자들의 정답수와 max를 비교하여 max에 제일 정답을 많이 맞춘 사람의 정답수를 담는 것이다.

그리하여 max와 수포자들의 정답수를 다시 비교하여
수포자의 정답수가 max와 같다면 정답을 많이 맞춘 순위를 배열로 표현한
answer에 담아주는 것이다.

answer => 정답을 많이 맞춘 순위를 배열로 표현

이 때 제일 많이 맞춘 사람이 한명이라면 answer에 해당 수포자한명이 담길 것이고 동일하게 다 많이 맞췄다면 person1,person2,person3 이렇게 순서대로 담길 것이다.
이는 위 for문의 k라는 변수로 순차적으로 순회할 수 있기 때문이다.

처음에 의문을 가졌던 문제의 고민들에 이제 답을 내릴 수 있다.

  1. 수포자1,2,3이 있는데 이들을 숫자 1,2,3으로 표현하여 answer에 담아야하는데 수포자들을 숫자(1,2,3)으로 표현할 수 있는 방법은 무엇이 있을까?

  2. 시험이 최대 10,000 문제라는 것은 코드로 구현해야하는 부분인 것인지, 아니면 코드의 효율성을 고려하여 문제에 대하여 코드를 구현해야된다는 것인지 의도 파악을 잘 못했다는 점

  3. 가장 많이 맞춘 사람이 중복된다면 오름차순(1,2,3)으로 정렬해줄 수 있는 방법은 무엇일까?

  4. 가장 많이 맞춘 사람의 답을 정답과 비교할 수 있는 방법은 무엇일까?

많은 고민이 있었지만 이 코드를 리뷰하고 나서 이 질문들에 대하여 간단히 답을 찾았다면 for문이라 할 수 있겠다.

for문으로 순회하여 각 수포자들을 숫자로 순차적으로 표현해주고 오름차순으로 정렬해줄수 있었으며 max라는 변수를 지정하여 point의 요소를 비교하여 가장 많이 맞춘 사람을 return해줄 수 있었다.

처음 코테문제를 생각하고 분석해본 나의 리뷰는 for문과 index의 활용하는 것이 중요하다는 깨달음을 얻고 간다.

첫 문제를 풀고나서..

나도 자료구조와 알고리즘을 공부하는 동시에 문제를 풀면서 실력을 빨리 쌓아나가고 싶다는 생각이 들었으며 이것이 개발의 묘미가 아닐까라는 생각도 들었다.

프론트엔드의 경우에 실제로 알고리즘을 적용할 일은 없다고 하지만 자료구조와 알고리즘을 공부하는 것은 개발의 본질에 가까워지려는 노력인 것 같다.

개발자란 어떠한 문제에 대하여 프로그래밍 언어로 해결할 수 있는 사람이라고 생각하는데 이를 위해선 알고리즘을 공부해야하는것은 적절하다는 생각이 든다.

알고리즘 공부와 코딩테스트 풀이 연습이 어떻게 도움이 될지는 몰라도 꾸준히 연습하여 코드로 문제에 대한 해결하는 능력을 키워 더더욱 즐거움을 느끼고 싶다.

참조: 첫번째 풀이

profile
FE DEVELOPER

0개의 댓글