목표
- 기존에 문제를 푸는데만 집중해서 풀었던 문제들을 클린 코드, 객체 지향 방식으로 리팩토링
- 완벽한 효율보다는 다양한 스타일로 작성
코테 문제) https://school.programmers.co.kr/learn/courses/30/lessons/142085
준호가 처음 가지고 있는 병사의 수 n, 사용 가능한 무적권의 횟수 k, 매 라운드마다 공격해오는 적의 수가 순서대로 담긴 정수 배열 enemy가 매개변수로 주어집니다. 준호가 몇 라운드까지 막을 수 있는지 return 하도록 solution 함수를 완성해주세요.
제한사항
from heapq import heappush,heappop
def solution(n, k, enemy):
answer = 0
h = []
for i,e_n in enumerate(enemy):
heappush(h,-e_n)
n-=e_n
if n < 0:
if k<=0:
return i
else:
n -= heappop(h)
k -= 1
return len(enemy)
from heapq import heappush, heappop
class Player:
def __init__(self, soldiers: int, chances: int):
self.__soldiers: int = soldiers
self.__chances: int = chances
self.__enemy_heap: list[int] = []
def fight_enemy(self, enemy: int) -> None:
self.__soldiers -= enemy
heappush(self.__enemy_heap, -enemy)
def use_chance(self) -> None:
if self.__enemy_heap and self.__chances > 0:
self.__soldiers -= heappop(self.__enemy_heap)
self.__chances -= 1
@property
def is_defeated(self) -> bool:
return self.__soldiers < 0 and self.__chances <= 0
@property
def current_soldiers(self) -> int:
return self.__soldiers
def solution(n: int, k: int, enemy: list[int]) -> int:
player = Player(n, k)
for _round, enemy_cnt in enumerate(enemy, start=1):
player.fight_enemy(enemy_cnt)
if player.current_soldiers < 0:
player.use_chance()
if player.is_defeated:
return _round - 1
return len(enemy)
개선점
Player
클래스를 정의해서 객체 지향 프로그래밍을 사용합니다. 코드의 재사용성, 확장성, 유지보수성을 높여줍니다Player
클래스의 is_defeated
및 current_soldiers
와 같은 프로퍼티를 통해 코드의 흐름을 더 직관적으로 표현합니다.Player
클래스가 전투와 관련된 로직을 담당하고 solution
함수는 전투의 흐름을 제어하는 역할을 하면서 역할 분리가 명확해집니다.fight_enemy
)과 기회를 사용하는 로직 (use_chance
)을 별도의 메서드로 분리하여 각 메서드가 하나의 책임만 가집니다. (단일 책임 원칙, Single Responsibility Principle)solution
함수에서 플레이어가 전투를 수행하고, 기회를 사용하는 과정이 더 직관적으로 이해됩니다.프로그래머스의 컴파일 옵션이 3.8 버전이므로
typing
을 사용해야 하지만 (list[int]
->List[int]
) 파이썬 3.9 이상부터는typing
없이 타입 힌트가 가능하므로 최근의 버전에 맞춰 작성했습니다.