풀이1번:
const combinations = function(menu, order, cnt, idx, prev) {
if (prev.length === cnt) {
let curStr = prev.sort().join(''); // 기존 주문 배열 내 원소가 주문 횟수만큼 있다면 원소들 문자로 생성
// 메뉴 객체에 기존 메뉴가 존재한다면 해당 메뉴 주문 횟수에 +1, 아니라면 새로 생성
if (menu.has(curStr)) menu.set(curStr, menu.get(curStr)+1);
else menu.set(curStr, 1);
}
// 기존 인덱스부터 문자열 하나씩 추가한 후 조합 재귀
for (let i = idx; i < order.length; i++) {
combinations(menu, order, cnt, i+1, [...prev, order[i]]);
}
}
function solution(orders, course) {
let menu = new Map(); // Map객체 생성: [['문자열 조합', 주문 횟수], ['문자열 조합', 주문 횟수], ...]
// 조합으로 주문 횟수에 따른 menu객체 완성시키기
orders.map(order => {
course.map(cnt => combinations(menu, order, cnt, 0, []));
});
// 주문 횟수 2회 이상인 메뉴들로 필터링
menu = [...menu.entries()].filter(elem => elem[1] >= 2).sort((a, b) => b.length - a.length);
let result = [];
course.map(cnt => {
let max = 0;
let tmp = menu.filter(([str, num]) => {
if (max < num && str.length === cnt) max = num;
return str.length === cnt;
})
tmp.filter(x => x[1] === max).map(x => result.push(x[0]));
})
// return 시 오름차순
return result.sort();
}
prev 는 order 의 문자열을 하나하나로 쪼개어 만들어진 모든 조합.
처음엔 아무것도 없으니 [] 빈 배열, 그후 주문 order[i] 번의 문자를 붙여 체크.
이중 course 만큼 길이가 같은것들만 curStr 에 저장. = 모든 콤비네이션들을 붙이고 저장.
그리고 menu 객체에 그 콤비네이션이 있나 비교하고 있으면 카운트 1 올려줌.
그리고 위에 보시다 싶이 다음 콤비네이션으로 비교하는 재귀함수
그리곤 메뉴에서 주문 횟수가 2이상인것만으로 filter 해줌.
후에 course 길이 [2,3,4] 대로 필터링하여 .map 해줌.
그리고, 제일 주문이 많이 된것들로 필터링을 합니다.
그리고 주문들만 result [] 배열에 push 해주고. 그후 오름차순으로 정렬을 해주고 그 값을 리턴 해줍니다.
풀이 2:
const combination = (arr, num) => {
let result = [];
//num이 1이 될때 까지 재귀함수를 통해 반복한다.
if (num === 1) return arr.map(e => [e]);
for (let i = 0; i < arr.length; i++) {
let rest = arr.slice(i+1)
let combinations = combination(rest, num-1)
//map함수를 통해 [i, + combinations[x]]를 합쳐준다.
let combiArr = combinations.map(x => [arr[i], ...x])
//result에 combiArr을 이어 붙여준다.
result.push(...combiArr)
}
return result
}
function solution(orders, course) {
//d : 메뉴의 조합
const d = new Map()
//m : 몇가지 조합인지
const m = new Map();
for (const order of orders) {
for (const n of course) {
for (let tmp of combination(order.split('').sort(), n)) {
//배열을 문자열로 변환
tmp = tmp.join('')
//d가 tmp를 가지고 있지 않으면 tmp : 0 삽입
if (!d.has(tmp)) d.set(tmp, 0);
//m이 n을 가지고 있지 않으면 n : 2 삽입
if (!m.has(n)) m.set(n, 2);
//d[tmp]의 값을 가져와서 1을 더함
const c = d.get(tmp) + 1
//m[n]의 값을 가져옴
const x = m.get(n)
//tmp의 개수 초기화
d.set(tmp, c)
//x와 c를 비교해서 더큰 값으로 초기화
m.set(n, x > c ? x : c)
}
}
}
//d의 요소에서 filter함수를 통해 value값이
//m 요소에서 d의 key값의 길이와 같은 값만 필터링 한 후
//map함수를 통해 key값만 추출한뒤 정렬
return Array.from(d.entries()).filter(([v,c]) => c == m.get(v.length)).map(([v,c]) => v).sort()
}