function combination(arr, n) {
const result = [];
if (n === 1) return arr.map(e => [e]);
arr.forEach((e,i,arr) => {
const copy = arr.slice(i+1);
const cases = combination(copy, n-1);
const combi = cases.map(v => [e, ...v]);
result.push(...combi);
})
return result;
}
function solution(orders, course) {
const answer = [];
course.forEach(num => {
const map = new Map();
orders.forEach(menu => {
const menuArr = menu.split('').sort();
const combinations = combination(menuArr, num);
combinations.forEach(e => {
const key = e.join('');
map.set(key, map.get(key) + 1 || 1);
})
})
const setMenu = [...map].sort((a,b) => b[1] - a[1]);
for (let i = 0; i < setMenu.length; i++) {
const max = setMenu[0][1];
if (max === 1) break;
if (setMenu[i][1] < max) break;
answer.push(setMenu[i][0]);
}
})
return answer.sort();
}
combination 재귀 함수를 통해 조합을 구현할 줄 아는 것이 핵심.
각각의 orders 요소에 구성되어있는 단품메뉴들 중 course 요소 개수만큼만 뽑아 조합을 구현합니다.
ex) 단품메뉴: ["ABCFG"], 개수: 2개 -> combination(단품메뉴, 개수) -> [["A","B"], ["A","C"], ["A","F"], ..., ["F","G"];
나온 각각의 조합을 key로 동일한 조합의 개수를 value로 map에 저장합니다.
combinations.forEach(e => {
const key = e.join('');
map.set(key, map.get(key) + 1 || 1);
})
/* map: [
[ 'AB', 1 ], [ 'AC', 4 ],
[ 'AF', 1 ], [ 'AG', 1 ],
[ 'BC', 2 ], [ 'BF', 2 ],
[ 'BG', 2 ], [ 'CF', 2 ],
[ 'CG', 2 ], [ 'FG', 2 ],
[ 'CD', 3 ], [ 'CE', 3 ],
[ 'DE', 3 ], [ 'AD', 2 ],
[ 'AE', 2 ], [ 'AH', 1 ],
[ 'CH', 1 ], [ 'DH', 1 ],
[ 'EH', 1 ]
] */
map을 배열로 만들어 [1]인덱스 기준으로 내림차순 정렬한 후에 max값들의 key만 뽑아서 정답으로 도출합니다.