프로그래머스 - 광물캐기(lv2)

김민기·2024년 5월 12일
0

알고리즘

목록 보기
9/9

언제까지 지속될지는 모르겠지만
매주 알고리즘 문제 1개씩 푸는것을 목표로 삼았다.
일요일에 풀고 있네...

문제 상세 내용은 링크를 통해 확인할 수 있다.
코딩테스트 연습 - 광물캐기

문제에 대한 내용은 필요한 부분만 작성한다.

문제 설명

다이아몬드 곡괭이, 철 곡괭이, 돌 곡괭이를 사용해서 광물을 채집해야 한다.
곡괭이는 아무거나 하나 선택할 수 있고 모든 곡괭이는 5번 사용할 수 있다.
단, 채집하는 광물의 순서를 바꿀 수는 없다.

어떤 곡괭이를 사용해서 광물을 채집하느냐에 따라 피로도가 다르다.
다이아몬드 곡괭이를 사용하면 어떤 광물이든 피로도가 1씩 쌓이지만
철 곡괭이를 사용하면 다이아몬드는 피로도가 5씩 쌓이고 나머지 광물은 1씩 쌓인다
돌 곡괭이를 사용하면 다이아몬드는 피로도가 25씩 쌓이고 철은 5씩 나머지는 1씩 쌓인다.

종류에 상관없이 곡괭이가 5개가 있다면
채집할 수 있는 횟수는 25번이 된다.
만약 광물의 갯수가 그 보다 많다면 (25개 초과) 작업은 종료된다.

이런 조건에서
최소한의 피로도를 반환할 수 있는 방법을 찾아야 한다.

주어지는 매개변수
picks - [1, 3, 2]
minerals - ["diamond", "diamond", "diamond", "iron", "iron", "diamond", "iron", "stone"]

아이디어

곡괭이의 갯수를 구해서 채집할 수 있는 총 횟수를 구한다.
총 횟수를 벗어나는 광물은 배열에서 제외시킨다.
어떤 곡괭이를 사용하더라도 한 번에 5번 밖에 사용할 수 없으므로 채집할 광물 배열을 5개씩 나눠야 한다.
객체를 사용해서 5개씩 나눈 배열을 추가하고, 5개씩 나눈 배열에서 "가중치"를 합산한다.

다이아몬드 3, 철 2, 돌 1

이차원 배열을 사용해서 다음과 같은 구조로 만들어야 한다.

[
  {
    array: [ 'diamond', 'diamond', 'diamond', 'iron', 'iron' ],
    weight: 13
  },
  { 
    array: [ 'diamond', 'iron', 'stone' ], 
   	weight: 6
  }
]

가중치를 사용해서 내림차순으로 정렬한다.
가중치가 크다는 것은 많은 피로도를 요구한다는 것이고 최소한의 피로도를 사용하기 위해서는
다이아몬드 곡괭이 -> 철 곡괭이 -> 돌 곡괭이 순으로 작업해야 한다.

코드

function solution(picks, minerals) {
    
    let diamondTools = picks[0]
    let ironTools = picks[1]
    let stoneTools = picks[2]
    
    let maxLen = picks.reduce((a,b) => a+b);
    if(maxLen === 0) return 0;
    
    minerals = minerals.splice(0, maxLen * 5)
    
    let fatigue = 0;
    const updatedMinerals = [];
        
    for(let i = 0; i < minerals.length; i+= 5) {
        let tempArray;
        let weight = 0;
        tempArray = minerals.slice(i, i + 5)
        tempArray.map((item) => {
            item === "diamond" ? weight += 25 : item === "iron" ? weight += 5 : weight += 1
        })
      	// 배열과 가중치를 갖는 객체를 추가한다.
        updatedMinerals.push({array: tempArray , weight})
    
    }
    
  	// 가중치를 기준으로 내림차순 정렬
    updatedMinerals.sort((a,b) => b.weight - a.weight)
    
  	// 곡괭이질 시작
    updatedMinerals.map((minerals) => {
        if(diamondTools !== 0) {
            minerals.array.forEach((item) => fatigue += 1)
            diamondTools--;
        } else if(ironTools !== 0) {
            minerals.array.forEach((item) => {
                if(item === "diamond") {
                    fatigue += 5
                } else {
                    fatigue += 1
                }
            })
            ironTools--;
        } else if(stoneTools !== 0){
            minerals.array.forEach((item) => {
                if(item === "diamond") {
                    fatigue += 25;
                } else if(item === "iron") {
                    fatigue += 5;
                } else {
                    fatigue += 1;
                }
            })
            stoneTools--;
        }
    })
    // 누적 피로도 반환
    return fatigue;
}

수정 사항

가중치를 3, 2, 1로 테스트를 했을 때, 코드 실행에서는 문제가 없었지만 제출했을 경우 실패하는 케이스가 발생했다. 다른 방법으로 풀어야 하나 궁금해서 다른 분들의 코드를 확인해봤는데
가중치를 사용하지 않고 5개의 배열에 다이아몬드, 철, 돌의 갯수를 기록하고 정렬할 때 다이아몬드 -> 철 -> 돌 기준으로 정렬하고 다이아몬드 곡괭이부터 사용해서 채집을 하도록 하고 있었다.

방법은 달라보이지만 기본적인 개념은 같다는 생각에 가중치를 활용할 수 있는 방법이 없을까 생각을 해봤는데
가중치를 너무 적게 주고 있다는 생각이 들었다.
실제로 다이아몬드를 채집할 때 다이아몬드 곡괭이와 돌 곡괭이의 채집 차이는 25배 정도이지만 내가 준 가중치로는 3배이다. 또한 철을 채집할 때 철 곡괭이와 돌 곡갱이의 채집 차이도 5배이지만 내가 준 가중치로는 2배이다.
따라서 다이아몬드 25 철 5 돌 1로 가중치를 수정하였고 테스트에 통과하였다.

제출은 성공했지만, 다른 케이스에서 또 문제가 발생하지 않을까 걱정되기는 함...

0개의 댓글