반응형
프로그래머스 lv2 메뉴 리뉴얼
레벨: 2
언어: JavaScript
문제 설명
레스토랑을 운영하던 스카피는 코로나19로 인한 불경기를 극복하고자 메뉴를 새로 구성하려고 고민하고 있습니다.
기존에는 단품으로만 제공하던 메뉴를 조합해서 코스요리 형태로 재구성해서 새로운 메뉴를 제공하기로 결정했습니다. 어떤 단품메뉴들을 조합해서 코스요리 메뉴로 구성하면 좋을 지 고민하던 "스카피"는 이전에 각 손님들이 주문할 때 가장 많이 함께 주문한 단품메뉴들을 코스요리 메뉴로 구성하기로 했습니다.
단, 코스요리 메뉴는 최소 2가지 이상의 단품메뉴로 구성하려고 합니다. 또한, 최소 2명 이상의 손님으로부터 주문된 단품메뉴 조합에 대해서만 코스요리 메뉴 후보에 포함하기로 했습니다.
예를 들어, 손님 6명이 주문한 단품메뉴들의 조합이 다음과 같다면,
(각 손님은 단품메뉴를 2개 이상 주문해야 하며, 각 단품메뉴는 A ~ Z의 알파벳 대문자로 표기합니다.)
입력 값
- orders: 손님들이 주문한 단품메뉴들이 문자열 형식으로 담긴 배열
- course: 코스요리를 구성하는 단품메뉴들의 갯수가 담긴 배열
출력 값
- result: 새로 추가하게 될 코스요리의 메뉴 구성을 문자열 형태로 담은 배열
📑풀이 아이디어
- 먼저 이 문제는 조합으로 쉽게 풀 수 있다.
- orders에 들어오는 문자열을 course의 수 만큼 뽑아서 조합을 만든다.
- 참고로 조합은 순서상관이 없다.
XY
나YX
나 같은 것으로 본다.
📋풀이 코드
function solution(orders, course) {
let answer = [];
let obj = {};
course.map((num) => {
orders.forEach((menu) => {
combination(menu.split(""), num).map((el) => {
const word = el.sort().join("");
obj[word] ? (obj[word] += 1) : (obj[word] = 1);
});
});
});
course.map((num) => {
let maxNum = 0;
for (const key in obj) {
if (obj[key] === 1) continue;
if (key.length === num) {
obj[key] > maxNum ? (maxNum = obj[key]) : "";
}
}
let temp = Object.keys(obj).filter((key) => {
return obj[key] === maxNum && key.length === num;
});
temp;
temp.map((el) => answer.push(el));
});
return answer.sort();
}
function combination(arr, num) {
const result = [];
if (num === 1) return arr.map((el) => [el]);
arr.forEach((fix, idx, array) => {
const restArray = array.slice(idx + 1);
const combiArr = combination(restArray, num - 1);
const combiFix = combiArr.map((el) => [fix, ...el]);
result.push(...combiFix);
});
return result;
}
함수 설명
function combination(arr, num) {
const result = [];
if (num === 1) return arr.map((el) => [el]);
arr.forEach((fix, idx, array) => {
const restArray = array.slice(idx + 1);
const combiArr = combination(restArray, num - 1);
const combiFix = combiArr.map((el) => [fix, ...el]);
result.push(...combiFix);
});
- 조합을 만드는 함수이다.
- 아래의 블로그를 참고하여 조합함수를 만들었다. 이 함수의 자세한 내용은 아래 블로그를 참조하기 바란다.
- 참고 블로그
코드 설명
course.map((num) => {
orders.forEach((menu) => {
combination(menu.split(""), num).map((el) => {
const word = el.sort().join(""); //정렬하고 join하여 순서에 상관없게 만든다.
obj[word] ? (obj[word] += 1) : (obj[word] = 1);
});
});
});
- course 배열의 모든 수와 orders의 모든 문자열의 조합을 만들기 위해 2중으로 map을 구성하였다.
- combination의 반환 값으로 조합의 배열이 넘어 오는데 배열의 요소(메뉴 구성 ex AB,)를 key로 하여 중복되어 나온 수를 카운트한다.
- 아래와 같은 형태로 객체가 만들어진다.
{ XY: 2, XZ: 1, YZ: 1, WX: 2, WY: 1, AW: 1, AX: 1, XYZ: 1, WXY: 1, AWX: 1 }
course.map((num) => {
let maxNum = 0;
for (const key in obj) {
if (obj[key] === 1) continue; // 1
if (key.length === num) { // 2
obj[key] > maxNum ? (maxNum = obj[key]) : "";
}
}
let temp = Object.keys(obj).filter((key) => { //3
return obj[key] === maxNum && key.length === num;
});
temp.map((el) => answer.push(el)); //4
});
- obj에서 가장 많이 나온 메뉴를 answer 배열에 넣기 위한 코드이다.
- 코스요리 메뉴는 최소 2가지 이상 되어야 함으로 1의 값은 continue한다.
- num 개의 요리 가지 수 중에서 가장 높은 수를 찾는다.
중복되는 숫자가 있을 수 있어 가장 높은 수를 찾은 다음 그 수에 맞는 요리를 선택했다. - 찾은 가장 높은 수와 같은 요리 조합을 filter로 걸러내서 temp에 담는다.
- 중복되는 값은 2개가 나올 수 있어서 하나씩 push한다.
return answer.sort();
- 사전 순서대로 정렬하여 정답을 제출한다.
이번 문제도 오래걸렸다.
조합과 순열을 코드로 구현해본적이 없어서 찾아보는데 시간이 오래 걸렸다.
재귀함수가 나오면 이해하기가 너무 어렵다.
알고리즘 특히 재귀함수를 더 공부해자
반응형
'지난 글 모음' 카테고리의 다른 글
[백준-node.js] JavaScript 입력 - vsCode에서 풀기 (0) | 2022.01.30 |
---|---|
[프로그래머스] LV1 다트게임 JavaScript (0) | 2022.01.29 |
[React Hooks] input onChange 사용법 (onChange)사용 예시 (0) | 2022.01.26 |
[프로그래머스] lv2 주차 요금 계산 JavaScript (0) | 2022.01.26 |
[프로그래머스] LV2 기능 개발 스택/큐 JavaScript (1) | 2022.01.25 |