프로그래머스: 메뉴 리뉴열

Song-Minhyung·2022년 6월 7일
0

Problem Solving

목록 보기
10/50
post-thumbnail

문제

https://programmers.co.kr/learn/courses/30/lessons/72411
여러명의 손님이 시킨 메뉴조합중 조합 개수별로 인기가 제일 높은 조합을 고르는 문제다.

입력: [orders, course]

  • orders: 2 이상 20이하의 배열길이
    • 각 원소: 길이가 2 이상 10이하인 문자열
      • 각 문자열은 대문자로만 이뤄져있음
      • 각 문자열은 같은 알파벳이 중복되자 않음
  • course: 1 이상 10 이하의 배열길이
    • 각 원소: 길이가 2이상 10이하인 자연수가 오름차순 정렬돼있음
      • 각 원소는 같은값이 중복되어 있지 않음

출력: 조합 개수별로 인기가 제일 높은 조합의 배열목록을 출력함

  • 배열에 저장된 알파벳들은 오름차순으로 정렬되어있음.
  • 주문횟수가 같다면 같은 조합 모두 배열에 저장함
  • orders, course는 무조건 return하는 배열 길이가 1이상이 되도록 주어짐.

문제풀이

정답을 구하는 과정은 간단하다.

  1. 입력으로 들어온 orders의 모든 조합을 구해서 조합의 주문 횟수를 계산한다.
  2. 1에서 구한 조합들중 주문 횟수가 제일 높은 조합을 구한다.
  3. 2의 결과를 오름차순으로 정렬 후 return해준다.
// 조합을 구하는 함수
function getCombination(input, end, start=0, result=[], tmp=[]) {
    if (tmp.length === end) {
        result.push(tmp);
        return;
    }
    for (let i=start; i<input.length; i++) {
        getCombination(input, end, i+1, result, [...tmp, input[i]]);
    }
    return result;
}

function solution(orders, course) {
    const resultCourse = {};
    const maxCntCombis = {};
    let result = [];

    // orders의 모든 조합을 계산함
    orders.forEach((order) => {
        // 매개변수로 넘어온 order문자열을 배열로 변환
        const orderArr = order.split("").sort();
        // 모든 course 순환
        course.forEach( (courseNum) => {
            // order배열의 course개 조합 
            // 문자열로 치환하고 1차원 배열로 바꿔줌
            const combis = getCombination(orderArr, courseNum)
                            .map( combi => combi.join(""));
            // reeulstCourse 객체에 해당 메뉴 조합을 주문한 횟수를 저장함
            combis.forEach( combi => {
                resultCourse[combi] = (resultCourse[combi] || 0) + 1;
            })
        });
    });
    // 계산한 조합에서 주문수가 가장 높은 조합만 저장함
    Object.entries(resultCourse).forEach( (v) => {
        const menuLength = v[0].length;
        const nowCombi = maxCntCombis[menuLength];
        const combi = v[0];
        const cnt = v[1];
        
        // 손님들이 두번 이상 주문한 메뉴라면
        if (cnt >= 2) {
            // 객체에 현재 조합이 있는경우
            if (nowCombi){
                // 객체에 저장된 조합보다 현재 조합의 주문횟수가 더 많은경우
                if (cnt > nowCombi.cnt) {
                    maxCntCombis[menuLength] = {
                        cnt,
                        combis: [combi]
                    }
                // 겍체에 저장된 조합과 현재 조합의 주문횟수가 같은경우
                }else if (cnt === nowCombi.cnt) {
                    maxCntCombis[menuLength].combis.push(combi);
                }
            } 
            // 객체에 현재 조합이 없는경우
            else {
                maxCntCombis[menuLength] = {
                    cnt,
                    combis: [combi]
                }
            }
        }
    });
    // 결과를 result에 저장함
    Object.entries(maxCntCombis).forEach ( (v) => {
        const combis = v[1].combis;
        combis.forEach ( (combi) => {
            result.push(combi);
        });
    });
    
    return result.sort();
}



const orders = ["ABCDE", "AB", "CD", "ADE", "XYZ", "XYZ", "ACD"]
const course = [2,3,5];
const a = solution(orders, course);
console.log(a);
profile
기록하는 블로그

0개의 댓글