문제
https://school.programmers.co.kr/learn/courses/30/lessons/172927
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
마인이 광물을 캐는 작업을 다 마칠 때까지 필요한 최소 피로도를 구하는 문제이다. 마인이 가진 곡괭이와 광물을 캐는 순서는 문제에서 주어지나, 종류별 곡괭이를 사용하는 순서는 정해져있지 않다.
마인이 광물을 캐는 작업을 다 마치는 기준은 '모든 광물을 캔 경우'와 '(광물이 남았어도) 더이상 사용할 수 있는 곡괭이가 없는 경우'이다.
리뷰
풀이
각 곡괭이로 각 광물을 캤을 때 필요한 피로도가 아래와 같이 주어진다.
곡괭이 하나 당 5번 사용할 수 있는데, 철 곡괭이로 다이아몬드를 한 번 캘 때의 피로도는 다이아몬드 곡괭이로 다이아몬드를 다섯 번 캘 때의 피로도와 같다. 돌 곡괭이와 철 곡괭이의 경우도 마찬가지이다.
이 조건 덕분에 '좋은 곡괭이로 좋은 광물을 많이 캐면 된다.'라는 기본적인 풀이가 쉽게 도출되는 것 같다. 이에 따라 광물 리스트를 곡괭이를 사용할 수 있는 횟수인 5개씩 슬라이싱하여, 각 슬라이스 별 광물 개수를 계산했다. 그리고 다이아몬드, 철, 돌이 많은 순서로 슬라이스를 정렬하여 좋은 곡괭이를 사용하도록 계산하도록 했다.
단 고려해야 할 점이 있다. 주어진 곡괭이로 모든 광물을 캘 수 없는 경우, 슬라이스를 정렬한 후 원래는 뒤에 있어 캘 수 없던 광물을 캐게 될 수도 있다. 광물을 캐는 순서는 정해져 있으므로 이는 오류이다. 따라서 광물을 캐기 전에 광물 리스트를 슬라이싱하여 주어진 곡괭이로 캘 수 있는 만큼으로 제한했다.
개인적으로는 Python 람다 문법을 사용한 지 오래되어 각 슬라이스를 다이아몬드, 철, 돌이 많은 순서로 정렬하는 방법을 생각하는 것이 오래 걸렸다.
코드
# 최소한의 피로도 = 다이아몬드 곡괭이로 최대한 많이 캔다.
def solution(picks, minerals):
answer = 0
diamond = [1, 1, 1]
iron = [5, 1, 1]
stone = [25, 5, 1]
# 전체 곡괭이로 광물을 전부 캘 수 없을 수도 있다.
# 전체 곡괭이로 캘 수 있는 만큼으로 minerals 리스트를 제한한다.
if (sum(picks) * 5 < len(minerals)):
minerals = minerals[:sum(picks)*5]
mineral_num = len(minerals)
pickax_needed = mineral_num//5
mineral_counts = []
for i in range(0,mineral_num,5):
mineral_count = {"diamond": 0, "iron": 0, "stone": 0}
if (i+5 >= mineral_num):
mineral_unit = minerals[i:]
else:
mineral_unit = minerals[i:i+5]
for mineral in mineral_unit:
mineral_count[mineral]+=1
mineral_counts.append(mineral_count)
sorted_mineral_counts = sorted(mineral_counts, key = lambda x: (-x["diamond"], -x["iron"], -x["stone"]))
# 각 곡괭이로 광물을 캘 때의 피로도를 계산한다.
for mineral_count in sorted_mineral_counts:
if picks[0] > 0:
answer+=get_fatigue(mineral_count, diamond)
picks[0]-=1
elif picks[1] > 0:
answer+=get_fatigue(mineral_count, iron)
picks[1]-=1
elif picks[2] > 0:
answer+=get_fatigue(mineral_count, stone)
picks[2]-=1
else:
break
return answer
# 피로도를 계산하는 함수
def get_fatigue(mineral_count, pick):
print(pick)
return (pick[0] * mineral_count["diamond"] + pick[1] * mineral_count["iron"] + pick[2] * mineral_count["stone"])
'Problem Solving' 카테고리의 다른 글
[프로그래머스/Lv.2] 두 원 사이의 정수 쌍 - Python (0) | 2024.03.22 |
---|---|
[프로그래머스/Lv.2] 석유 시추 - Python (0) | 2024.03.21 |
[프로그래머스/Lv.1] 개인정보 수집 유효기간 - Python (0) | 2024.02.28 |
[프로그래머스/Lv.2] H-Index - Java (0) | 2023.04.28 |
[프로그래머스/Lv.2] 의상 - Java (0) | 2023.04.28 |