(프로그래머스) 위장

大 炫 ·2021년 2월 14일
0

프로그래머스

목록 보기
2/7

사실 알고리즘에 부좀함을 많이느껴서 공부를 한 뒤 위장이라는 문제를 처음 접했는데..
며칠간 공부했으니까 검색은 최소한으로 하자는 마음가짐이..
이렇게 오랫동안 문제를 잡게할 줄 몰랐던거지,,

아무튼 결국 풀어낸 문제는 상당한 길이의 코드이며,, 1번 테스트에서 시간초과로 96.4점이라는 점수 밖에 못 받았지만 나름 복습할만한 내용들을 담았기에 글을 남기려고한다.

문제의 해결과정은 다음과같다.

"서로다른" 옷의 조합
기존 clothes라는 매개변수로 받아온 배열이

[["crow_mask", "face"], ["green_turban", "headgear"],["blue_sunglasses", "eyewear"],["blue_sunglasses,", "face"]]

name과 category로 이루어진 배열을 category에 따라서
key값과 value값에 따라 배열을 다시 만들어줬다.

redupCheck라는 변수는 앞으로 저장될 cate를 문자열로 저장 !

앞으로 저장될 cate와 비교,
해당 변수를 split을 통해 배열로 만든뒤 인덱스 요소에서 찾고
같은 cate가 존재한다면 findIndex를 통해 이미 존재하는 배열에 push

그렇게 완성된 newArr이라는 배열이다.

그리고 완성된 배열을 조합에 바로 집어넣으면
육안으로 조합을 console.log를 찍으면서 확인할때 불편할 듯 하여,
newArr과 같은 형태의 0으로만 채운 배열을 만들어서 조합을 진행했다.

위의 log결과를 보면 0번째 인덱스에 길이가 2인 배열이 들어갔는데 이는

다음과 같은 코드의 else에 해당하는 splice를 거쳤기때문이다.
if문의 조건은 newArr이라는 배열을 filter를 통해 새로운 배열을 반환하는데
조건으로는 .length의 길이가 1 이상인 것들
즉, 같은 category를 가진 요소가 존재해서 배열의 길이가 2이상이 존재한다면 filter함수에서 살아남는 친구들이 존재할 것이고,
기존 매개변수인 clothes가 모두 다른 cate를 가지고있다면, 모든인덱스요소인 배열의 크기가 1이 되기때문에 filter함수에서 나온 배열은 크기가 0이 될것이다.
크기가 0이라면 for문을 통해 조합을 돌려 빠르게 종료시킬 생각이었는데
이것도,, 시간초과,,

조합은 다음과 같은데 이곳에서 조합의 코드를 그대로 사용했다.

그렇게 마지막으로 splice된 ckeck라는 배열을 위의 조합과 사용한 방법은 아래와같다.

먼저 배열 len은 조합에 넣어야될 숫자들로 채웠고
res는 len에 담긴 숫자들을 조합에 넣어준 결과로 채워줬다.
각기 다른 cate의 배열이 3가지가 존재하기때문에 최대 3가지의 조합이 나올 수 있다.
그래서 len이

이 되는 것이고,
각각의 결과를 combination에 넣어준 결과가

res가 되는것이다.
res의 0번째 인덱스는 1가지 조합의 경우,
1번째 인덱스는 2가지 조합의 경우,
2번째 인덱스는 3가지 조합의 경우에 해당한다.

여기서 고민했던 부분이 기존 combination의 함수를 수정해서 res를 모든 조합의 수가 존재하는 배열로 받는다면
ex) [1,2,3] 이라는 배열을 combination에 넣었을 경우

위의 결과와같은 res에 넣을 수 있게 되어 한층 더 깔끔한 코드가 될 수 있었을 텐데 문제를 해결하는데 급급하여 코드가 엄청 지저분하게 됬다.
(작성을 끝내고 타인의 해결코드를 확인하고 리팩토링을 하려고 한다.)

또 len이라는 배열이 아니라 forEach안에서 for문을 통해 combination을 호출하는 막장같은 코드속에서 런타임에러가 발생하여,, 나름 임시방편으로 해결해놓은 수준이라 ㅠ
어렵게 해결한 만큼 리팩토링의 과정이 사실 더 기대된다.

그렇게 지저분한 res를 해결한 과정은 이렇다.
res를 좀더 깊게 살펴보자.

이렇게 생겼는데 0으로 바꿔놓으니까 더 어렵게 보일 수도 있겠다..
해서 newArr을 check라는 새로운 배열로 바꾸지 않고 조합에 넣게되면 이런 결과를 얻는다. 그 중 1번째 인덱스(2가지 조합의 경우)에 해당한다.

face라는 공통 cate를 일단 모두 묶어서 1가지 옷이라고 생각한 결과이다.
그리고 그 결과안에서

다음과 같은 코드로 마지막 결과를 이끌어냈다.
기존 countNum은 당연히 0이고,
이중 forEach문 안에서 배열이 존재하는가 ?
라는 if문에서 존재하지 않는다면 indexOf는 -1,
즉,

위의 경우처럼 같은 cate가 존재하지 않는 요소끼리 조합한 경우의 수가 되고,
그런 경우의 수는 1가지 조합밖에 존재하지 않으니까
countNum = countNum + 1;

만약 이중 forEach문 안에서 배열이 존재한다면 ?

위와같은 결과는 1가지 조합의 경우가 아닌
실제로는 1 * 2 의 2가지 경우의 수가 나오기때문에
reduce를 통한 곱셈을 통해 countNum을 증가시켜줌으로써

종료시점에 return되어질 countNum은 모든 경우의 수를 더한 값이 된다.

참.. 어렵게도 풀었는데 풀면서도 고민할 가치가 충분했던 문제라고 생각했기때문에
오랜 시간을 들여 해결한 문제였다.(시간초과문제는 미해결)

알고리즘과 다양한 메서드를 통한 깔끔한 코드 작성,
가독성 좋은 변수명,,

좋은 코드라는 만족은
끝이 보이지않을 만큼 점점 더 멀어지지만,
먼 길이 그리 지루하게 느껴지지 않을 듯하다.

profile
대현

0개의 댓글