[프로그래머스][PCCP 기출문제] 1번 / 붕대 감기

2400·2024년 2월 17일
0

문제
제 설명
어떤 게임에는 붕대 감기라는 기술이 있습니다.

붕대 감기는 t초 동안 붕대를 감으면서 1초마다 x만큼의 체력을 회복합니다. t초 연속으로 붕대를 감는 데 성공한다면 y만큼의 체력을 추가로 회복합니다. 게임 캐릭터에는 최대 체력이 존재해 현재 체력이 최대 체력보다 커지는 것은 불가능합니다.

기술을 쓰는 도중 몬스터에게 공격을 당하면 기술이 취소되고, 공격을 당하는 순간에는 체력을 회복할 수 없습니다. 몬스터에게 공격당해 기술이 취소당하거나 기술이 끝나면 그 즉시 붕대 감기를 다시 사용하며, 연속 성공 시간이 0으로 초기화됩니다.

몬스터의 공격을 받으면 정해진 피해량만큼 현재 체력이 줄어듭니다. 이때, 현재 체력이 0 이하가 되면 캐릭터가 죽으며 더 이상 체력을 회복할 수 없습니다.

당신은 붕대감기 기술의 정보, 캐릭터가 가진 최대 체력과 몬스터의 공격 패턴이 주어질 때 캐릭터가 끝까지 생존할 수 있는지 궁금합니다.

붕대 감기 기술의 시전 시간, 1초당 회복량, 추가 회복량을 담은 1차원 정수 배열 bandage와 최대 체력을 의미하는 정수 health, 몬스터의 공격 시간과 피해량을 담은 2차원 정수 배열 attacks가 매개변수로 주어집니다. 모든 공격이 끝난 직후 남은 체력을 return 하도록 solution 함수를 완성해 주세요. 만약 몬스터의 공격을 받고 캐릭터의 체력이 0 이하가 되어 죽는다면 -1을 return 해주세요.

==========================

문제를 풀기 위해 알아야 하는 지식

==========================

문제를 풀기 위한 아이디어

  • 예제 확인시, 시간(t) 업데이트 -> 몬스터 어택 이벤트가 있는 경우, 붕대 이벤트보다 어택 이벤트가 먼저 처리되는 것을 인지함. 어택 이벤트가 없는 경우, 붕대 이벤트가 진행됨
  • 결과적으로 문제에서 주어진대로 풀면 되는 문제였다.
  • 그런데 여러가지 예외처리를 어떻게 해야할지 대략 난감하였다.
  • ex1) 붕대보다 몬스터 어택이 먼저 처리되나?
  • ex2) 최대 체력을 초과한 붕대 감기 이벤트
  • ex3) 붕대감기 완료시 발생하는 추가 체력 회복 이벤트
  • ex4) 최소 체력을 초과한 사망 이벤트

후기 : 함수화를 진행해서 반복되는 코드는 제거할걸..;;

def solution(bandage, health, attacks):     
    def check(current_t,current_hp,hp_diff,current_continuous_success_cnt,attack,first_attack_info_key,attack_info):
        print(
            'current_t',current_t
            ,'current_hp',current_hp
            ,'hp_diff',hp_diff
            ,'success_cnt',current_continuous_success_cnt
            ,'attack',attack
            ,'first_attack_info_key',first_attack_info_key
            # ,attack_info[first_attack_info_key]['attack_t']
        )
    
    attack_info = {}
    for i,attack in enumerate(attacks):
        tmp_dic = {}
        tmp_dic['attack_t'] = attack[0]
        tmp_dic['attack_dmg'] = attack[1]
        attack_info[i] = tmp_dic
        
    current_t = 0
    current_hp = health
    current_continuous_success_cnt = 0
    
    band_t = bandage[0]
    band_spd = bandage[1]
    band_etc_hp = bandage[2]
    
    max_hp = health
    
    print(
        'current_t',current_t
        ,'current_hp','hp_diff',current_hp,0
        ,'success_cnt',current_continuous_success_cnt
        ,'attack',0
    )
    # seq : time_update- > is_attacked -> hp_update
    first_attack_info_key = 0
    for i in range(1,10000):
        current_t += 1
        
        # attack event
        if (
            (current_t == attack_info[first_attack_info_key]['attack_t'])
        ):
            attack = 1
            current_continuous_success_cnt = 0
            hp_diff = attack_info[first_attack_info_key]['attack_dmg']
            expected_current_hp = current_hp - hp_diff
            if expected_current_hp<=0:
                current_hp = 0
                print('hp under 0 break')
                return -1
            if expected_current_hp>0:
                current_hp = current_hp - hp_diff
            
            first_attack_info_key += 1
            
            check(
                current_t,current_hp,hp_diff
                ,current_continuous_success_cnt,attack,first_attack_info_key
                ,attack_info
            )
            
            if first_attack_info_key == len(attacks):
                print('last attack',current_t,first_attack_info_key,len(attacks))
                return current_hp
                break
        # band event
        elif (
            (current_t != attack_info[first_attack_info_key]['attack_t'])
        ):
            if current_continuous_success_cnt >= band_t-1:
                attack = 0
                current_continuous_success_cnt = 0
                band_before_current_hp = current_hp
                hp_diff = band_spd + band_etc_hp
                expected_current_hp = current_hp + hp_diff
                if expected_current_hp >= max_hp:
                    current_hp = max_hp
                if expected_current_hp <= max_hp:
                    current_hp = expected_current_hp
                
                hp_diff = current_hp - band_before_current_hp
                
                check(
                    current_t,current_hp,hp_diff
                    ,current_continuous_success_cnt,attack,first_attack_info_key
                    ,attack_info
                )
            elif current_continuous_success_cnt < band_t-1:
                attack = 0
                current_continuous_success_cnt = current_continuous_success_cnt + 1
                band_before_current_hp = current_hp
                hp_diff = band_spd
                expected_current_hp = current_hp + hp_diff
                if expected_current_hp >= max_hp:
                    current_hp = max_hp
                if expected_current_hp <= max_hp:
                    current_hp = expected_current_hp
                
                hp_diff = current_hp - band_before_current_hp
                
                check(
                    current_t,current_hp,hp_diff
                    ,current_continuous_success_cnt,attack,first_attack_info_key
                    ,attack_info
                )


    answer = 0
    return answer
profile
공부용 혹은 정리용 혹은 개인저장용

0개의 댓글