프로그래머스 LEVEL 2(광물 캐기)

image

  • 사용 언어 : javascript

  • 해결 날짜 : 2023-04-25

  • 해결 방법 :

    • 갖고 있는 곡괭이로 캘 수 있는 광물로만 minerals 재구성
    • minerals를 돌며 5개씩 총 광물의 피로도를 누적 계산 후 arr에 push
      • 예를 들어 [diamond, diamond, iron, iron, stone]이면 36 * 3(diamond) + 6 * 2(iron) + 1 * 1 (stone) = 121
    • 내림차순 정렬한 arr를 돌며 다이아몬드 곡괭이, 철 곡괭이, 돌 곡괭이를 순서대로 사용하며 피로도 계산
      • 이 때 더 이상 사용할 수 있는 곡괭이가 없다면 종료
  • 회고 :

    • 처음에 작성한 코드.
    • 갖고 있는 곡괭이로 캘 수 있는 광물에 대해 다이아몬드: 30, 철: 5, 돌: 1의 값을 부여해주었다.

      function solution(picks, minerals) {
        let answer = 0;
      
        const totalPicks = picks.reduce((acc, cur) => acc + cur, 0);
        minerals = minerals.slice(0, totalPicks * 5);
        const totalMinerals = minerals.length;
      
        let temp = 0;
        const arr = [];
      
        minerals.forEach((mineral, i) => {
          switch (mineral) {
            case 'diamond':
              temp += 30;
              break;
            case 'iron':
              temp += 5;
              break;
            case 'stone':
              temp += 1;
              break;
          }
      
          if ((i + 1) % 5 === 0 || i + 1 === totalMinerals) {
            arr.push(temp);
            temp = 0;
          }
        });
      
        arr
          .sort((a, b) => b - a)
          .forEach((v) => {
            const diamond = Math.floor(v / 30);
            v %= 30;
            const iron = Math.floor(v / 5);
            v %= 5;
            const stone = v;
      
            if (picks[0]) {
              picks[0] -= 1;
              answer += diamond + iron + stone;
            } else if (picks[1]) {
              picks[1] -= 1;
              answer += diamond * 5 + iron + stone;
            } else if (picks[2]) {
              answer += diamond * 25 + iron * 5 + stone;
            } else {
              return false;
            }
          });
      
        return answer;
      }
      
    • 그러나 테스트 케이스 8, 9, 20에서 실패했다.

      image

    • 생각해보니 현재 로직은 두번째 forEach에서 각 다이아몬드, 철, 돌의 갯수를 구할 때 v가 5인 경우 [0, 1, 0]이 나오는 문제가 발생했다. 따라서 각 광물의 값을 더할 때 30, 5, 1이 아닌 36, 6, 1로 로직을 수정했다. 그 결과 성공!!

      image

    • 풀고 나서 생각해보니 첫번째 forEach문에서 각 광물의 값을 더하는게 아닌 광물의 갯수를 arr에 담아주면 더 간단하게 풀 수도 있을 것 같다.
  • 코드

    function solution(picks, minerals) {
      let answer = 0;
    
      const totalPicks = picks.reduce((acc, cur) => acc + cur, 0);
      minerals = minerals.slice(0, totalPicks * 5);
      const totalMinerals = minerals.length;
    
      let temp = 0;
      const arr = [];
    
      minerals.forEach((mineral, i) => {
        switch (mineral) {
          case 'diamond':
            temp += 36;
            break;
          case 'iron':
            temp += 6;
            break;
          case 'stone':
            temp += 1;
            break;
        }
    
        if ((i + 1) % 5 === 0 || i + 1 === totalMinerals) {
          arr.push(temp);
          temp = 0;
        }
      });
    
      arr
        .sort((a, b) => b - a)
        .forEach((v) => {
          const diamond = Math.floor(v / 36);
          v %= 36;
          const iron = Math.floor(v / 6);
          v %= 6;
          const stone = v;
    
          if (picks[0]) {
            picks[0] -= 1;
            answer += diamond + iron + stone;
          } else if (picks[1]) {
            picks[1] -= 1;
            answer += diamond * 5 + iron + stone;
          } else if (picks[2]) {
            answer += diamond * 25 + iron * 5 + stone;
          } else {
            return false;
          }
        });
    
      return answer;
    }
    
  • 출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges