<프로그래머스, 체육복 빌려주기 문제>

Minwoong Kim·2022년 9월 6일
0

2022-Sep-06, today getting out of my comfort zone.

문제 설명

도둑이 들어 일부 학생이 체육복을 도난당했다. 체육복이 없는 사람은 수업에 참여할 수 없는데, 다행히 여벌이 있는 학생이 있어 체육복을 빌려주려 한다.
단,

  1. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호나 뒷번호의 학생에게만 빌려줄 수 있으며,
  2. 전체 학생 수는 2명 이상 30명 이하이다.
  3. 또한, 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없다.
  4. 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복은 없다.
  5. 여벌을 가져온 사람이 도난당했을 경우, 이 학생은 빌려주지 않는다.

전체 학생 수를 n, 도난 당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생의 번호가 담긴 reserve가 주어질 때, 체육 수업을 들을 수 있는 학생의 최댓값을 return 하는 solution 함수를 작성해라.

접근 방식

n명의 모든 학생들이 각 1벌 씩의 체육복을 갖고 있다고 가정하자. 그리고 배열을 순회하며 체육복의 도난 여부와 여벌의 체육복 유무에 따라 -1, +1 등의 연산을 통해 도난 당한 후의 각 학생들의 체육복 갯수를 나타내는 배열을 만든 후, 가장 많은 학생이 체육복을 가질 수 있도록 분배하는 작업을 구현해보자.

Comfort zone


Step-1

let nArray = new Array(n).fill(1);

n개의 요소를 가지는 배열을 생성하고, fill 메서드를 통해 각 요소에 1을 넣어준다. 배열 요소의 순서에 따라 추상적으로 번호가 부여되었다고 생각했을 때, n=5 라면 [1,1,1,1,1] 에서 nArray[0] 은 1번 학생, nArray[1] 은 2번 학생이 된다.


Step-2

for(let i=1; i<=n; i++){
 if(lost.includes(i) === true && reserve.includes(i) === false){
 nArray[i-1] -= 1;} 
 
 else if(lost.includes(i) === false && reserve.includes(i) ===true){
 nArray[i-1] += 1;}
 
 else if(lost.includes(i) === true && reserve.incldues(i) === true){
 nArray[i-1] += 0;}
 
 else if(lost.includes(i) === false && reserve.includes(i) === false){
 nArray[i-1] += 0;
 }

for문을 통해 순회하면서, 특정 index가 lost 배열이나 reserve 배열에 포함되어 있는지 검사한다.

위에서부터 아래까지 차례로,

  1. 잃어버렸으나 여벌이 없는 경우
  2. 잃어버리지 않았으며 여벌이 있는 경우
  3. 잃어버렸으나 여벌이 있는 경우
  4. 잃어버리지 않았으며 여벌이 없는 경우

를 나타낸 것이다.


Step-3

for(let j=0; j<nArray.length; j++){
    if(nArray[j]===0){
        if(nArray[j-1]===2){
            nArray[j] +=1;
            nArray[j-1] -=1;
        }else if(nArray[j-1]!==2 && nArray[j+1]===2){
            nArray[j] +=1;
            nArray[j+1] -=1;
        }else if(nArray[j-1]===2 && nArray[j+1]===2){
            nArray[j] +=1;
            nArray[j-1] -=1;
        }
    }
}

전 단계에서 완성된 nArray를 살펴보자. 만약 완성된 배열이
[2, 0, 2, 0, 0]
라고 가정해보자. 여기서 nArray[2]nArray[1]에 1을 주게 되면, nArray[0]은 체육복을 줄 수가 없다. [2, 1, 1, 0, 0]이 되니까!(바로 앞뒤에만 줄 수 있다는 조건에 의해)

따라서, nArray를 순회하면서 특정 index에서의 값이 0일 때, 바로 전 값이 2인 경우를 우선으로 분배하도록 코드를 작성했다.


Step-4
마지막으로 forEach문을 활용하여 배열의 요소가 0인 것들을 count하도록 했다. 그리고 nArray 배열의 길이에서 count 값을 빼주며 0이 아닌 값들의 갯수를 구할 수 있었다.

Getting ouf of comfort zone

성능적으로 유의미한 차이는 없을 것 같지만.... 최근에 배운 function을 이용하여 객체를 생성하는 방법과 해당 객체에 접근하는 방식을 응용해보기 위해 한 번 시도해보았다.

또한, 체육복을 분배하는 과정에서(Step-3) 불필요한 로직이 포함되어 있어 좀 더 간결하게 만들었다.

마지막으로, 답을 return 하기 위한 과정에서(Step-4) nArray 중 0인 요소를 카운트하고 원래 배열의 길이를 구하고, 또 다시 배열의 길이에서 0인 요소의 갯수를 빼는 과정이 쓸데없이 복잡하다는 생각이 들었다.

해서, 좀 더 직관적으로 답을 구하기 위해 filter 함수를 사용해보았다. 조건에 만족하는 값들을 필터링하여 그 갯수를 그대로 answer에 할당하였다. 좀 더 우아한 코드가 된 것 같기도 하고...

끝!

profile
Get out of my comfort zone

0개의 댓글