지난포스트 (deprecated)/Algorithm & Data Structure (deprecated)

[코딩테스트 연습] 위장 ★★

.log('FE') 2018. 12. 3. 15:07
728x90
반응형

 

 

 

 

위장 링크

 

 

입출력 예

 

clothes return
[ ["yellow_hat", "headgear"], ["blue_sunglasses", "eyewear"], ["green_turban", "headgear"] ] 5
[ ["crow_mask", "face"], ["blue_sunglasses", "face"], ["smokey_makeup", "face"] ] 3



풀이

 

function solution (clothes) {
let newArr = clothes.map(a => a[1]);
let unique = newArr.filter(function(item, pos) {
return newArr.indexOf(item) == pos;
});
let result = {};
let numberCase = 1
for(let i in newArr) {
if(!(newArr[i] in result)) {
result[newArr[i]] = [];
result[newArr[i]].push(newArr[i]);
} else {
result[newArr[i]].push(newArr[i]);
}
};
for(let j in unique) {
numberCase = (result[unique[j]].length + 1) * numberCase;
};
return numberCase - 1;
}


 

풀이설명

 

모든 경우의 수를 구할 코드를 짜려고했는데 너무 비효율적이기도 했고 누군가 달아준 힌트 덕분에 코드가 나아가야 할 방향을 잡을 수 있게 되었습니다.

 

그말인즉슨 '모든 경우의 수를 다 구할 필요는 없다. 예를들면 모자:3, 얼굴:2, 외투:1 이라면 (3+1) * (2+1) * (1+1) - 1 = 23의 경우의 수를 구할 수 있다.' 그러니까 이 문제에서의 패턴을 찾고 그 패턴으로 만들어 낼수 있는 공식을 활용하여 그렇게 돌아가도록 코드를 짜면 되는것이다.

 

코드라 너무 어렵게 생각했는데 말 그대로 주어진 문제에서 모든 경우의 수를 구하는 것이다.

 

여기서의 조건은 무조건 한가지 또는 그 이상의 옷을 입는다는것, 같은 이름을 가진 의상은 없다는것 위의 공식을 풀자면

 

모자1,

모자2,

모자3,

안쓸경우

 

얼굴1,

얼굴2,

안쓸경우

 

외투1,

안입을경우

 

여기서 마지막에 -1 이 붙은건 모든 옷을 하나도 입지 않을경우의 공통의 수 1가지를 빼는것이다.

 

그래서 코드구성을 하기전에 생각했던것이

 

그렇다면 각 부위당 몇개의 옷을 갖고있는지 알 수 있다면 나머지는 숫자계산만 해주면 된다고 생각했고

 

주어진 배열이 [ [의상이름, 의상의 종류] ] 에서 의상의 종류에 초점을 맞추기로 했습니다.

 

1. newArr

새로운 배열을 하나 생성할건에 이 배열에는 전체 배열중에 의상의 종류만 따로 담는 배열을 만들려고 생각했고 map 함수로 전체 배열을 돌면서 중첩배열의 index(1) 에 해당하는 값인 의상의 종류만 뽑아서 새 변수에 담았고 newArr 에 들어간 배열은 ["headgear", "eyewear", "headgear"] 입니다.

 

2. unique

이 새로 생성된 배열중에 중복된 값을 지우고 전체를 통틀어 단일한 값은 하나만 남겨두는 코드를 작성하고 변수에 담았습니다. 나중에 전체 배열에서 해당값이 있으면 해당값:Array(갯수) 인 key와 value의 형태로 배열안에 담아두려고 하는 사전 작업입니다. unique 에 들어간 배열은 ["headgear", "eyewear"] 입니다.

 

["headgear", "eyewear", "headgear"] 배열을 filter 함수로 전체 배열을 돌면서 item 인자는 배열의 값을 받고 pos 인자는 index 의 값을 전달 받습니다.

 

그리고 true가 나오는 값만 다시 배열로 변수에 담아주게 됩니다.

 

item "headgear", pos = 0,
newArr.indexOf("headgear") == 0 // true

item "eyewear", pos = 1,
newArr.indexOf("eyewear") == 1 // true

item "headgear", pos = 2,
newArr.indexOf("headgear") == 2 // false

 

마지막에서 false 가 나온이유는 indexOf 는 배열에서 가장 왼쪽에 있는 값을 먼저 찾기때문에 비교값은 0 == 2 가되버리고 false 값이 나오게 됩니다.

 

따라서 중복된 값이 없이 새로운 단일값을 가진 새로운 배열을 만들어 줄 수 있습니다.

 

3. result

원하는 목록인 의상의종류:배열 를 담을 빈 배열객체를 선언하고

 

4. numberCase

나중에 곱셈의 값을 받아 저장할 변수이기 때문에 0이 아니라 1로 초기화 값을 잡았습니다.

 

5. 첫번째 for

제일 처음에 만들어 두었던 변수를 돌면서 만약 result 배열안에 newArr[i]("headgear", "eyewear", "headgear") 에 있는 값이 없다면 newArr[i] 이름으로 빈 배열을 생성하고 그 안에 newArr[i] 값을 넣어주고

 

result 배열안에 비교값이 있을경우에는

 

그 있는 값또한 해당 배열에 푸쉬를 시킵니다.

 

그러면

{headgear: Array(2), eyewear: Array(1)} 이러한 key 와 value 를 가진 객체가 생성되고

 

eyewear: ["eyewear"]

headgear: ["headgear", "headgear"]

 

 

이렇게 값을 가지게 됩니다.

 

 

6. 두번째 for

두번쨰 for 에서는 uniqe 의 배열 갯수만큼 반복하면서 numberCase 에 (의상의종류.length + 1) * numberCase 의 수식을 넣어주고

 

7. 마지막 함수의 리턴값으로 최종값에서 아무것도 입지않았을 경우의 수인 1을 빼준 값을 리턴해주게 됩니다.

 

 

이렇게까지 작성하는데 20줄이 소모되었고 전체적으로 프로그래머스에서의 테스트는 모두 통과하였습니다.

 

다른사람의 풀이를 보는데 가장 짧게 해결한 코드가 6줄........아.... 저렇게도 되는구나....

 

 

다른사람의 풀이

 

가장 짧게 작성한 코드는 Object.values() 를 사용하여 내가 map이며 filter 며 for문이며 복잡하게 구현한걸 다 집어 넣었다.

 

Object.values()  메소드는 전달된 파라미터가 가지는 key:value 형태의 값중에서 value 값만 리턴해 주는 매소드로 괄호 안에서 구현해줄 부분은 key:value 형태로 만들어주는 작업만 하면 된다.

 

그걸 reduce 라는 배열 매소드를 사용하여

 

obj, t 라는 인자를 받고 ex)  obj = ["blue_sunglass", "headgear"], t = 0

 

obj[t[1]] = obj[t[1]] ? obj[t[1]] + 1 : 1;

 

이 계산이 다 끝난 obj 배열을 리턴해주고 이걸 한번더 reduce 매소드를 활용하여 계산 수식까지 끝냈다.


 

배열의 매소드 활용에 대한 부분을 좀더 연습해봐야겠지만

 

어쨋든 난이도 2였던 코딩테스트 연습문제도 해결을 한것에 있어서는 기분이 좋다.

 

code-reading 블로그에 방문해 주셔서 환영합니다.
댓글은 모두 환영하니 많이 달아주세요.

728x90
반응형