본문 바로가기
코테연습

55. 체육복 Javascript

by hxunz 2022. 5. 31.

https://programmers.co.kr/learn/courses/30/lessons/42862

 

코딩테스트 연습 - 체육복

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번

programmers.co.kr

 

 

1. 문제에 대한 이해

  • 우리가 풀어야 할 문제는 무엇인가?
     - 체육 수업을 듣기 위해서는 체육복이 있어야한다.
     - 체육복 도난 당한 학생들이 여벌의 체육복이 있는 학생들한테 빌려서 체육 수업을 들을 수 있는 학생들은 총 몇명인가?
  • 주어진 자료는 무엇인가?
     - n = 전체 학생 수
     - lost = 체육복 도난 당한 학생들의 번호
     - reverse = 여벌의 체육복이 있는 학생들의 번호
  • 조건은 무엇인가?
     - 전체 학생 수는 2명 이상 30명 이하이다.
     - 체육복 도난 당한 학생 중에 중복되는 번호는 없다.
     - 여벌의 체육복을 가진 학생 중에 중복되는 번호는 없다.
     - 여벌 체육복을 가진 학생이 체육복 도난 당했으면 체육복이 한개 남기 때문에 빌려줄 수 없다.
     - 여벌 체육복을 가진 학생은 자신의 번호 n-1 혹은 n+1 학생에게만 빌려줄 수 있다.

  • 숨겨진 조건이나 자료가 있는가? 그렇다면 그 것을 다른 방법으로 해석해보라.
     - 여벌 체육복이 있는 학생의 총 체육복 개수는 2벌이다.
     - 여벌 체육복이 있는 학생들은 무조건 체육 수업을 들을 수 있다.
 

2. 계획

  • 전에 비슷한 문제를 알고 있는가?
     - 코테 완주하지 못한 선수에서 요소를 찾고 찾은 요소는 배열에서 제거 시켰는데 이부분을 활용할 수 있으려나,,
     - https://hxunz.tistory.com/167?category=1030034 
  • 이 문제를 푸는데 있어서 유용하게 쓸 수 있는 지식은 무엇인가?
     - 이중반복문
     - filter()

 

  1. reserve의 요소와 lost의 요소가 같다면
    각각의 배열에서 해당 요소 제거
  2. 이걸 새로운 변수 newReserve, newLost 에 담아준다.

  3. 이제 이 둘의 배열을 반복문을 통해서 비교해보자
  4. 반복문은 reserve의 요소를 n-1 한것과 n+1 한 것 두번 이중으로 돌아야(?)할것이다.

  5. 우선, newReserve 요소가 전부 n-1일 경우를 계산해보자
  6. 만약 newReserve의 요소를 -1 했을 때 newLost에서 해당하는 숫자가 있다면
  7. newReserve와 newLost에서 각각 그 요소를 제거한다.

  8. 그 다음에 newReserve 요소가 전부 n+1인 경우
  9. 만약에 newReserve의 요소를 +1 했을 때 newLost에서 해당하는 숫자가 있다면
  10. newReserve와 newLost에서 각각 그 요소를 제거한다.

  11. 이때, newLost의 길이가 0이라면 (모두가 체육복을 빌려입은것이겠지,,)
  12. 전체 학생 수 n을 리턴

  13. newLost의 길이가 1이상이라면,
  14. 전체 학생 수 - 체육복 못 빌린 학생
  15. 여기서 체육복 못 빌린 학생은 위에서 체육복 빌려입고 거르고 걸러진 newLost의 길이이다.
 

3. 실행

  • 풀이 계획을 실행하고, 각 단계가 올바른지 점검하라.
const solution = (n, lost, reserve) => {
  let newLost = lost.filter(it => !reserve.includes(it)).sort();
  let newReserve = reserve.filter(it => !lost.includes(it)).sort(); 

  for (i = 0; i < newReserve.length; i++) {
    for (j = 0; j < newLost.length; j++) {
      if (newReserve[i] - 1 === newLost[j]) {
        newReserve.splice(i, 1);
        i--;
        newLost.splice(j, 1);
        j--;
      }
      if (newReserve[i] + 1 === newLost[j]) {
        newReserve.splice(i, 1);
        i--;
        newLost.splice(j, 1);
        j--;
      } 
    }
  }
  
  return (newLost.length === 0) ? n : n - newLost.length;
};

test('체육수업에 참가할 학생 수 ', () => {
  expect(solution(5, [2, 4], [1, 3, 5])).toEqual(5);
  expect(solution(5, [2, 3], [3])).toEqual(4);
});

 

4. 반성

  • 문제를 다른 방식으로 해결할 수 있는가?
     - for 대신에 forEach나 map을 사용할 수도 있을것같다.
  • 결과나 방법을 어떤 다른 문제에 활용할 수 있는가?
     - 다른 그리디 문제를 풀때나 두 개의 배열을 비교할때, 배열의 요소를 제거할때 활용할 수 있을것같다.

 

 

Facts & Findings

처음에는 계획 대강 세우고 filter()만 사용해서 교집합, 차집합;; 이용해서  풀려고 했다. 

나 조차도 이해 안되는 변수명과 코드를 보니 뭔가 아니다 싶어서 다 갈아엎고 

계획부터 머릿속으로 생각하면서 작성을 해 나갔고

계획대로 코드를 작성했고

테스트 코드를 실행해보니 통과가 됐다. 

 

계획 단계의 중요성을 다시 한번 느끼게 되었다.

계획은 자세히 세울수록 문제 이해도 쉽고 구현하기에도 편한것같다. 

귀찮아하지말고 계획을 잘 세우자!!

'코테연습' 카테고리의 다른 글

57. 부족한 금액 계산하기 Javascript  (0) 2022.06.08
56. 폰켓몬 Javascript  (0) 2022.05.31
54. 모의고사 Javascript  (0) 2022.05.29
53. 문자열압축 Javascript  (0) 2022.05.27
52. K번째수 Javascript  (0) 2022.05.25

댓글