반응형
    
    
    
  
                              Notice
                              
                          
                        
                          
                          
                            Recent Posts
                            
                        
                          
                          
                            Recent Comments
                            
                        
                          
                          
                            Link
                            
                        
                    | 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 | 
| 12 | 13 | 14 | 15 | 16 | 17 | 18 | 
| 19 | 20 | 21 | 22 | 23 | 24 | 25 | 
| 26 | 27 | 28 | 29 | 30 | 31 | 
                            Tags
                            
                        
                          
                          - 소켓
- HTTP
- 알고리즘
- 자바스크립트
- 프로그래머스
- Crawling
- 프로그래머스 레벨 2
- 쉬운 문제
- dfs
- dp
- ip
- 백준
- 타입 챌린지
- 크롤링
- Node.js
- Algorithm
- typescript
- 문자열
- 그래프
- HTTP 완벽 가이드
- BFS
- 수학
- javascript
- 가천대
- Nestjs
- 레벨 1
- 타입스크립트
- type challenge
- TCP
- socket
                            Archives
                            
                        
                          
                          - Today
- Total
kakasoo
[node.js] 메뉴 리뉴얼 ( 프로그래머스 레벨2 ) 본문
반응형
    
    
    
  /**
 * 1. 단품 메뉴들의 합집합을 만든다.
 * 2. 단품 메뉴들의 조합을 만든다. ( 중복은 제거하고, length가 2 이상. )
 * 3. 조합들과 손님의 주문을 각각 비교하여 횟수를 구한다.
 * 4. 각 팔린 횟수 중에서 가장 메뉴 가짓수length가 큰 것을 뽑는다.
 */
const sortString = (str) =>
    str.sort((a, b) => {
        const aStr = a.split("");
        const bStr = b.split("");
        while (aStr.length && bStr.length) {
            const aCode = aStr.shift().charCodeAt();
            const bCode = bStr.shift().charCodeAt();
            if (aCode === bCode) {
                continue;
            } else {
                return aCode - bCode;
            }
        }
        return aStr.length - bStr.length;
    });
// const makeSumSet = (orders) => {
//     const sumSet = Array.from(new Set(orders.map((el) => el.split('')).flat(Infinity)));
//     return sumSet.sort((a,b) => {
//         const aCode = a.charCodeAt();
//         const bCode = b.charCodeAt();
//         return aCode - bCode;
//     });
// }
const isCommonSet = (main, sub) => {
    for (const cur of sub) {
        if (!main.includes(cur)) {
            return false;
        }
    }
    return true;
};
const getCombination = (arr, num) => {
    const answer = [];
    if (num === 1) {
        return arr.map((e) => [e]);
    }
    arr.forEach((el, i, arr) => {
        const rest = arr.slice(i + 1);
        const combinations = getCombination(rest, num - 1);
        const combinationArr = combinations.map((el2) => [el, ...el2]);
        if (combinationArr.length) {
            for (let i = 0; i < combinationArr.length; i++) {
                if (i > 11000) {
                    return answer;
                }
                answer.push(combinationArr[i]);
            }
        }
    });
    return answer;
};
const solution = (orders, course) => {
    // 1. 단품 메뉴들의 합집합을 만든다.
    // const allMenues = makeSumSet(orders);
    // 내가 틀린 가장 큰 문제 중 하나로, 합집합을 해버리면, 조합 때 엄청난 크기의 배열이 된다
    // 2. 단품 메뉴들의 조합을 만든다.
    // const combinations = [];
    // course.forEach((el) => {
    //     combinations.push(...getCombination(allMenues, el));
    // })
    const temp = [];
    course.forEach((el) => {
        for (const order of orders) {
            temp.push(...getCombination(sortString(order.split("")), el));
        }
    });
    // const ans = Array.from(new Set(temp.map((el) => el.join(''))));
    // console.log(ans);
    // console.log(Array.from(new Set(temp)));
    const combinations = Array.from(new Set(temp.map((el) => el.join("")))).map(
        (el) => el.split("")
    );
    // 3. 조합들과 손님의 주문을 각각 비교하여 횟수를 구한다.
    const orderArr = [];
    const result = new Array(orders.length + 1).fill(0);
    for (let i = 0; i < result.length; i++) {
        result[i] = [];
    }
    orders.forEach((order) => orderArr.push(order.split("")));
    combinations.forEach((combination, index) => {
        let count = 0;
        for (const order of orderArr) {
            if (isCommonSet(order, combination)) {
                count++;
            }
        }
        if (count) {
            result[count].push(combination.join(""));
        }
    });
    // 4. 각 팔린 횟수 중에서 가장 메뉴 가짓수length가 큰 것을 뽑는다.
    const dishes = [];
    course.forEach((num) => {
        for (let i = result.length - 1; i >= 2; i--) {
            const max = result[i].filter((el) => el.length === num);
            if (max.length) {
                dishes.push(max);
                break;
            }
        }
    });
    return sortString(dishes.flat(Infinity));
};
나는 난이도가 상당하다고 느꼈다. 내가 생각한 방식은 주석으로 모두 나타냈다.
개인적으로 문제 자체가 설명을 잘 못한다고 느꼈다.
풀고 나니 문제가 다른 의미라는 걸 두세 번 정도 깨달아가며 겨우 풀었다.
반응형
    
    
    
  '프로그래밍 > 알고리즘 풀이' 카테고리의 다른 글
| [node.js] 이진 변환 반복하기 ( 프로그래머스 레벨2 ) (0) | 2021.07.01 | 
|---|---|
| [node.js] 행렬 테두리 회전하기 ( 프로그래머스 레벨2 ) (0) | 2021.06.30 | 
| [node.js] 뉴스 클러스터링 ( 프로그래머스 레벨2 ) (0) | 2021.06.30 | 
| [node.js] 배달 ( 프로그래머스 레벨2 ) (0) | 2021.06.30 | 
| [node.js] 예상 대진표 ( 프로그래머스 레벨2 ) (0) | 2021.06.30 | 
 
                   
                   
                  